diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index a1bcf15..24fff81 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -2,7 +2,7 @@
name: Bug report
about: Create a report to help us improve
title: "[BUG]"
-labels: ''
+labels: bug
assignees: ''
---
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index e0c0168..f455865 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -2,7 +2,7 @@
name: Feature request
about: Suggest an idea for this project
title: "[FEATURE]"
-labels: ''
+labels: enhancement
assignees: ''
---
diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index 601780b..c0c3369 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -2,9 +2,9 @@ name: .NET
on:
push:
- branches: [ "2.2" ]
+ branches: [ "2.4" ]
pull_request:
- branches: [ "2.2" ]
+ branches: [ "2.4" ]
jobs:
build:
@@ -21,3 +21,34 @@ jobs:
run: dotnet restore
- name: Build
run: dotnet build --no-restore
+ - name: Push package
+ run: |
+ # Grab some versioning information
+ commithash=$(git rev-parse --short HEAD)
+ currtime=$(date +%s)
+ echo "commit hash is $commithash"
+ echo "time is $currtime"
+
+ # Enter project directory
+ cd Mirai.Net
+
+ # Build package
+ dotnet restore
+ dotnet build
+
+ # Pack a nuget package with all the default config
+ dotnet pack
+
+ # Enter package output directory
+ cd bin/Debug
+
+ # Getting file named with .nupkg extension
+ file=""
+ cdir=`ls ./*.nupkg`
+ for eachfile in $cdir
+ do
+ file=$eachfile
+ done
+
+ # Push it to source "nuget"
+ dotnet nuget push $file --api-key ${{ secrets.NUGET_KEY }} --source "nuget" --skip-duplicate
diff --git a/.gitignore b/.gitignore
index add57be..efc7268 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,6 @@ bin/
obj/
/packages/
riderModule.iml
-/_ReSharper.Caches/
\ No newline at end of file
+/_ReSharper.Caches/
+/.vs/
+/MSBuild_Logs
diff --git a/.idea/.idea.Mirai.Net/.idea/encodings.xml b/.idea/.idea.Mirai.Net/.idea/encodings.xml
deleted file mode 100644
index df87cf9..0000000
--- a/.idea/.idea.Mirai.Net/.idea/encodings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/.idea.Mirai.Net/.idea/indexLayout.xml b/.idea/.idea.Mirai.Net/.idea/indexLayout.xml
deleted file mode 100644
index 7b08163..0000000
--- a/.idea/.idea.Mirai.Net/.idea/indexLayout.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/.idea.Mirai.Net/.idea/inspectionProfiles/Project_Default.xml b/.idea/.idea.Mirai.Net/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 3018bff..0000000
--- a/.idea/.idea.Mirai.Net/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/.idea.Mirai.Net/.idea/projectSettingsUpdater.xml b/.idea/.idea.Mirai.Net/.idea/projectSettingsUpdater.xml
deleted file mode 100644
index 4bb9f4d..0000000
--- a/.idea/.idea.Mirai.Net/.idea/projectSettingsUpdater.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/.idea.Mirai.Net/.idea/statistic.xml b/.idea/.idea.Mirai.Net/.idea/statistic.xml
deleted file mode 100644
index d588f64..0000000
--- a/.idea/.idea.Mirai.Net/.idea/statistic.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/.idea.Mirai.Net/.idea/vcs.xml b/.idea/.idea.Mirai.Net/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/.idea.Mirai.Net/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Mirai.Net.Test/Mirai.Net.Test.csproj b/Mirai.Net.Test/Mirai.Net.Test.csproj
index 3ed0572..a10ab02 100644
--- a/Mirai.Net.Test/Mirai.Net.Test.csproj
+++ b/Mirai.Net.Test/Mirai.Net.Test.csproj
@@ -2,7 +2,7 @@
Exe
- net5.0
+ net6.0
latest
@@ -11,7 +11,7 @@
-
+
diff --git a/Mirai.Net.Test/Module1.cs b/Mirai.Net.Test/Module1.cs
index be1f620..0c53a6a 100644
--- a/Mirai.Net.Test/Module1.cs
+++ b/Mirai.Net.Test/Module1.cs
@@ -1,10 +1,8 @@
using System;
using System.Linq;
-using Mirai.Net.Data.Commands;
using Mirai.Net.Data.Messages;
using Mirai.Net.Data.Messages.Concretes;
using Mirai.Net.Data.Messages.Receivers;
-using Mirai.Net.Data.Modules;
using Mirai.Net.Modules;
using Mirai.Net.Utils.Scaffolds;
@@ -15,23 +13,21 @@ public class Module1 : IModule
public async void Execute(MessageReceiverBase @base)
{
var receiver = @base.Concretize();
+ if (receiver.Sender.Id != "2933170747")
+ {
+ return;
+ }
var plain = receiver.MessageChain.GetPlainMessage();
-
- if (plain.CanExecute())
+ if (plain == "/off")
{
- var command = receiver.MessageChain.GetPlainMessage().ParseCommand();
- await receiver.SendMessageAsync(command.Value);
+ IsEnable = false;
+ await receiver.SendMessageAsync("Current module will be turned off");
+ return;
}
+ await receiver.SendMessageAsync(plain);
}
public bool? IsEnable { get; set; }
-
- [CommandEntity(Name = "say", Identifier = "/")]
- class SayCommand
- {
- [CommandArgument(Name = "v", IsRequired = true)]
- public string Value { get; set; }
- }
}
}
\ No newline at end of file
diff --git a/Mirai.Net.Test/Program.cs b/Mirai.Net.Test/Program.cs
index cce0478..94af642 100644
--- a/Mirai.Net.Test/Program.cs
+++ b/Mirai.Net.Test/Program.cs
@@ -1,25 +1,21 @@
using System;
-using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
+using System.Net;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
-using AHpx.Extensions.JsonExtensions;
-using AHpx.Extensions.StringExtensions;
-using Flurl;
-using Mirai.Net.Data.Commands;
-using Mirai.Net.Data.Events.Concretes.Message;
+using Manganese.Array;
+using Manganese.Text;
+using Mirai.Net.Data.Events.Concretes.Request;
using Mirai.Net.Data.Messages;
using Mirai.Net.Data.Messages.Concretes;
using Mirai.Net.Data.Messages.Receivers;
-using Mirai.Net.Data.Modules;
using Mirai.Net.Data.Sessions;
-using Mirai.Net.Data.Shared;
using Mirai.Net.Sessions;
using Mirai.Net.Sessions.Http.Managers;
-using Mirai.Net.Utils;
+using Mirai.Net.Utils.Internal;
using Mirai.Net.Utils.Scaffolds;
+using Newtonsoft.Json;
namespace Mirai.Net.Test
{
@@ -29,43 +25,24 @@ private static async Task Main()
{
var exit = new ManualResetEvent(false);
- using var bot = new MiraiBot
+ var bot = new MiraiBot
{
- Address = "localhost:8080",
+ Address = new ConnectConfig
+ {
+ HttpAddress = new ConnectConfig.AdapterConfig("localhost", "8080"),
+ WebsocketAddress = new ConnectConfig.AdapterConfig("localhost", "8080")
+ },
VerifyKey = "1145141919810",
- QQ = "2672886221"
+ QQ = "1590454991"
};
await bot.LaunchAsync();
var modules = new Module1().GetModules();
-
- bot.MessageReceived
- .OfType()
- .Subscribe(async r =>
- {
- modules.SubscribeModule(r);
+ bot.MessageReceived.WithModules(modules);
- // await r.SendMessageAsync(r.MessageChain.Append());
- });
-
+ Console.WriteLine("launched");
exit.WaitOne();
}
}
-
- [CommandEntity(Name = "test")]
- class TestCommand
- {
- [CommandArgument(Name = "arg1")]
- public string Arg1 { get; set; }
-
- [CommandArgument(Name = "arg2", Default = 114514)]
- public int Arg2 { get; set; }
-
- [CommandArgument(Name = "arg3")]
- public string[] Arg3 { get; set; }
-
- [CommandArgument(Name = "arg4")]
- public bool Arg4 { get; set; }
- }
}
\ No newline at end of file
diff --git a/Mirai.Net.UnitTest/CommandShould.cs b/Mirai.Net.UnitTest/CommandShould.cs
index 230578e..48ba57a 100644
--- a/Mirai.Net.UnitTest/CommandShould.cs
+++ b/Mirai.Net.UnitTest/CommandShould.cs
@@ -1,5 +1,4 @@
-using Mirai.Net.Data.Commands;
-using Mirai.Net.Utils.Scaffolds;
+
using Xunit;
namespace Mirai.Net.UnitTest;
@@ -18,7 +17,7 @@ public class CommandShould
[InlineData("/test-arg4 awd awd -arg5 114.514")]
public void CanExecute(string command)
{
- Assert.True(command.CanExecute());
+
}
[Theory]
@@ -30,39 +29,13 @@ public void CanExecute(string command)
[InlineData("/test -arg2 a -arg4 -arg5 awd")]
public void CantExecute(string command)
{
- Assert.False(command.CanExecute());
- }
-
- [CommandEntity(Name = "test")]
- class TestClass
- {
- [CommandArgument(Name = "arg1")]
- public string Arg1 { get; set; }
-
- [CommandArgument(Name = "arg2")]
- public int Arg2 { get; set; }
-
- [CommandArgument(Name = "arg3")]
- public string[] Arg3 { get; set; }
-
- [CommandArgument(Name = "arg4")]
- public bool Arg4 { get; set; }
- [CommandArgument(Name = "arg5")]
- public double Arg5 { get; set; }
}
-
- [CommandEntity(Name = "test")]
- class DefaultClass
- {
- [CommandArgument(Name = "arg4", IsRequired = true)]
- public bool Arg4 { get; set; }
- }
-
+
[Fact]
public void CantExecuteDefault()
{
- Assert.False("/test -arg4".CanExecute());
+
}
}
\ No newline at end of file
diff --git a/Mirai.Net.UnitTest/Mirai.Net.UnitTest.csproj b/Mirai.Net.UnitTest/Mirai.Net.UnitTest.csproj
index bdf3e4f..f124b77 100644
--- a/Mirai.Net.UnitTest/Mirai.Net.UnitTest.csproj
+++ b/Mirai.Net.UnitTest/Mirai.Net.UnitTest.csproj
@@ -1,7 +1,7 @@
- net5.0
+ net6.0
false
@@ -10,13 +10,13 @@
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/Mirai.Net/Data/Commands/CommandArgumentAttribute.cs b/Mirai.Net/Data/Commands/CommandArgumentAttribute.cs
deleted file mode 100644
index 46f0453..0000000
--- a/Mirai.Net/Data/Commands/CommandArgumentAttribute.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-
-namespace Mirai.Net.Data.Commands;
-
-[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
-public class CommandArgumentAttribute : Attribute
-{
- ///
- /// 参数名,比如"arg1"之于"/test -arg1"
- ///
- public string Name { get; set; }
-
- ///
- /// 参数是否为必须,如果是必须参数不填会报错,与Default冲突,二者选其一
- ///
- public bool IsRequired { get; set; } = false;
- //
- // ///
- // /// 是否为默认参数,默认参数即为不需要指定参数名的参数,默认参数只会解析紧随命令标识其后的参数,与IsRequired冲突,二者选其一
- // ///
- // public bool IsDefault { get; set; }
-
- ///
- /// 参数的默认值,与IsRequired冲突,二者选其一
- ///
- public object Default { get; set; } = null;
-}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Commands/CommandEntityAttribute.cs b/Mirai.Net/Data/Commands/CommandEntityAttribute.cs
deleted file mode 100644
index 02a0997..0000000
--- a/Mirai.Net/Data/Commands/CommandEntityAttribute.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-
-namespace Mirai.Net.Data.Commands;
-
-[AttributeUsage(AttributeTargets.Class)]
-public class CommandEntityAttribute : Attribute
-{
- ///
- /// 此命令的正式名称,比如"test"之于"/test"
- ///
- public string Name { get; set; }
-
- ///
- /// 此命令的别名,比如"/t"和"/tst"等价于"/test"
- ///
- public string[] Alias { get; set; } = { };
-
- ///
- /// 命令参数分隔符,比如"-"之于"/test -arg1 xxx -arg2 yyy"",默认为"-"
- ///
- public string Separator { get; set; } = "-";
-
- ///
- /// 命令的标识符,比如"/"之于"/test",默认为"/"
- ///
- public string Identifier { get; set; } = "/";
-}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Bot/DroppedEvent.cs b/Mirai.Net/Data/Events/Concretes/Bot/DroppedEvent.cs
index 250e84f..8cedb19 100644
--- a/Mirai.Net/Data/Events/Concretes/Bot/DroppedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Bot/DroppedEvent.cs
@@ -2,9 +2,18 @@
namespace Mirai.Net.Data.Events.Concretes.Bot;
-public class DroppedEvent : EventBase
+///
+/// Bot被服务器断开或因网络问题而掉线
+///
+public record DroppedEvent : EventBase
{
+ ///
+ /// Bot的QQ号
+ ///
[JsonProperty("qq")] public string QQ { get; private set; }
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.Dropped;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Bot/OfflineEvent.cs b/Mirai.Net/Data/Events/Concretes/Bot/OfflineEvent.cs
index dab5201..a2a79b4 100644
--- a/Mirai.Net/Data/Events/Concretes/Bot/OfflineEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Bot/OfflineEvent.cs
@@ -3,11 +3,17 @@
namespace Mirai.Net.Data.Events.Concretes.Bot;
///
-/// Bot自身事件
+/// Bot主动离线
///
-public class OfflineEvent : EventBase
+public record OfflineEvent : EventBase
{
+ ///
+ /// Bot的QQ号
+ ///
[JsonProperty("qq")] public string QQ { get; private set; }
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.Offline;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Bot/OfflineForceEvent.cs b/Mirai.Net/Data/Events/Concretes/Bot/OfflineForceEvent.cs
index c35e68c..726fec7 100644
--- a/Mirai.Net/Data/Events/Concretes/Bot/OfflineForceEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Bot/OfflineForceEvent.cs
@@ -2,9 +2,18 @@
namespace Mirai.Net.Data.Events.Concretes.Bot;
-public class OfflineForceEvent : EventBase
+///
+/// Bot被挤下线
+///
+public record OfflineForceEvent : EventBase
{
+ ///
+ /// Bit的QQ号
+ ///
[JsonProperty("qq")] public string QQ { get; private set; }
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.OfflineForce;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Bot/OnlineEvent.cs b/Mirai.Net/Data/Events/Concretes/Bot/OnlineEvent.cs
index e86366d..205dbe9 100644
--- a/Mirai.Net/Data/Events/Concretes/Bot/OnlineEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Bot/OnlineEvent.cs
@@ -5,9 +5,15 @@ namespace Mirai.Net.Data.Events.Concretes.Bot;
///
/// Bot自身事件
///
-public class OnlineEvent : EventBase
+public record OnlineEvent : EventBase
{
+ ///
+ /// Bot的QQ号
+ ///
[JsonProperty("qq")] public string QQ { get; private set; }
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.Online;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Bot/ReconnectedEvent.cs b/Mirai.Net/Data/Events/Concretes/Bot/ReconnectedEvent.cs
index 9dd6aab..36ac2e8 100644
--- a/Mirai.Net/Data/Events/Concretes/Bot/ReconnectedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Bot/ReconnectedEvent.cs
@@ -2,9 +2,18 @@
namespace Mirai.Net.Data.Events.Concretes.Bot;
-public class ReconnectedEvent : EventBase
+///
+/// Bot主动重新登录
+///
+public record ReconnectedEvent : EventBase
{
+ ///
+ /// Bot的QQ号
+ ///
[JsonProperty("qq")] public string QQ { get; private set; }
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.Reconnected;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Friend/FriendInputStatusChangedEvent.cs b/Mirai.Net/Data/Events/Concretes/Friend/FriendInputStatusChangedEvent.cs
index 4bee85d..8d0c5ba 100644
--- a/Mirai.Net/Data/Events/Concretes/Friend/FriendInputStatusChangedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Friend/FriendInputStatusChangedEvent.cs
@@ -2,8 +2,14 @@
namespace Mirai.Net.Data.Events.Concretes.Friend;
-public class FriendInputStatusChangedEvent : EventBase
+///
+/// 好友输入状态改变
+///
+public record FriendInputStatusChangedEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.FriendInputStatusChanged;
///
diff --git a/Mirai.Net/Data/Events/Concretes/Friend/FriendNickChangedEvent.cs b/Mirai.Net/Data/Events/Concretes/Friend/FriendNickChangedEvent.cs
index 2178801..07cf7cf 100644
--- a/Mirai.Net/Data/Events/Concretes/Friend/FriendNickChangedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Friend/FriendNickChangedEvent.cs
@@ -2,8 +2,14 @@
namespace Mirai.Net.Data.Events.Concretes.Friend;
-public class FriendNickChangedEvent : EventBase
+///
+/// 好友昵称改变
+///
+public record FriendNickChangedEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.FriendNickChanged;
///
diff --git a/Mirai.Net/Data/Events/Concretes/Friend/FriendRecalledEvent.cs b/Mirai.Net/Data/Events/Concretes/Friend/FriendRecalledEvent.cs
index c2eecfd..4f2ee4e 100644
--- a/Mirai.Net/Data/Events/Concretes/Friend/FriendRecalledEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Friend/FriendRecalledEvent.cs
@@ -2,8 +2,15 @@
namespace Mirai.Net.Data.Events.Concretes.Friend;
-public class FriendRecalledEvent : EventBase
+
+///
+/// 好友撤回了某条消息
+///
+public record FriendRecalledEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.FriendRecalled;
///
diff --git a/Mirai.Net/Data/Events/Concretes/Group/DisbandedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/DisbandedEvent.cs
new file mode 100644
index 0000000..e8d2ab6
--- /dev/null
+++ b/Mirai.Net/Data/Events/Concretes/Group/DisbandedEvent.cs
@@ -0,0 +1,33 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Mirai.Net.Data.Events.Concretes.Group
+{
+
+ ///
+ /// Bot因群主解散群而退出群
+ ///
+ public record DisbandedEvent : EventBase
+ {
+
+ ///
+ /// 事件类型
+ ///
+ public override Events Type { get; set; } = Events.Disbanded;
+
+ ///
+ /// Bot所在被解散的群的信息
+ ///
+ [JsonProperty("group")]
+ public Shared.Group Group { get; set; }
+
+ ///
+ /// Bot离开群后获取操作人的 Member 对象
+ ///
+ [JsonProperty("operator")]
+ public Shared.Member Operator { get; set; }
+
+ }
+}
diff --git a/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedAnonymousChatEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedAnonymousChatEvent.cs
index 9ad4a52..d287dd4 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedAnonymousChatEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedAnonymousChatEvent.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class GroupAllowedAnonymousChatEvent : GroupSettingChangedEventBase
+///
+/// 群内是否允许匿名聊天的状态改变
+///
+public record GroupAllowedAnonymousChatEvent : GroupSettingChangedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.GroupAllowedAnonymousChat;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedConfessTalkChanged.cs b/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedConfessTalkChanged.cs
index 5bea7b9..23ad734 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedConfessTalkChanged.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedConfessTalkChanged.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class GroupAllowedConfessTalkChanged : GroupSettingChangedEventBase
+///
+/// 群内是否允许坦白说的状态发生改变
+///
+public record GroupAllowedConfessTalkChanged : GroupSettingChangedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.GroupAllowedConfessTalk;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedMemberInviteEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedMemberInviteEvent.cs
index b670dff..5d68eff 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedMemberInviteEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/GroupAllowedMemberInviteEvent.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class GroupAllowedMemberInviteEvent : GroupSettingChangedEventBase
+///
+/// 群内是否允许群员邀请新成员的状态发生改变
+///
+public record GroupAllowedMemberInviteEvent : GroupSettingChangedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.GroupAllowedMemberInvite;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/GroupEntranceAnnouncementChangedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/GroupEntranceAnnouncementChangedEvent.cs
index b211ab9..7124f47 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/GroupEntranceAnnouncementChangedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/GroupEntranceAnnouncementChangedEvent.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class GroupEntranceAnnouncementChangedEvent : GroupSettingChangedEventBase
+///
+/// 入群公告发生改变
+///
+public record GroupEntranceAnnouncementChangedEvent : GroupSettingChangedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.GroupEntranceAnnouncementChanged;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/GroupMemberSettingChangedEventBase.cs b/Mirai.Net/Data/Events/Concretes/Group/GroupMemberSettingChangedEventBase.cs
index 421827f..a7ade83 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/GroupMemberSettingChangedEventBase.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/GroupMemberSettingChangedEventBase.cs
@@ -3,10 +3,20 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public abstract class GroupMemberSettingChangedEventBase : EventBase
+///
+/// 群成员设置改变基类
+///
+///
+public abstract record GroupMemberSettingChangedEventBase : EventBase
{
+ ///
+ /// 原来的值
+ ///
[JsonProperty("origin")] public T Origin { get; set; }
+ ///
+ /// 当前的值
+ ///
[JsonProperty("current")] public T Current { get; set; }
///
diff --git a/Mirai.Net/Data/Events/Concretes/Group/GroupMessageRecalledEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/GroupMessageRecalledEvent.cs
index 93c5e3d..8ab28ee 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/GroupMessageRecalledEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/GroupMessageRecalledEvent.cs
@@ -3,8 +3,14 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class GroupMessageRecalledEvent : EventBase
+///
+/// 某条群消息被撤回
+///
+public record GroupMessageRecalledEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.GroupMessageRecalled;
///
diff --git a/Mirai.Net/Data/Events/Concretes/Group/GroupMutedAllEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/GroupMutedAllEvent.cs
index 5eaa1cb..78b04c1 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/GroupMutedAllEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/GroupMutedAllEvent.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class GroupMutedAllEvent : GroupSettingChangedEventBase
+///
+/// 某群开启/关闭了全员禁言
+///
+public record GroupMutedAllEvent : GroupSettingChangedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.GroupMutedAll;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/GroupNameChangedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/GroupNameChangedEvent.cs
index 0b81e35..3b0415a 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/GroupNameChangedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/GroupNameChangedEvent.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class GroupNameChangedEvent : GroupSettingChangedEventBase
+///
+/// 某群的改了群名
+///
+public record GroupNameChangedEvent : GroupSettingChangedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.GroupNameChanged;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/GroupSettingChangedEventBase.cs b/Mirai.Net/Data/Events/Concretes/Group/GroupSettingChangedEventBase.cs
index d771260..0d14687 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/GroupSettingChangedEventBase.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/GroupSettingChangedEventBase.cs
@@ -3,7 +3,11 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public abstract class GroupSettingChangedEventBase : EventBase
+///
+/// 群设置改变基类
+///
+///
+public abstract record GroupSettingChangedEventBase : EventBase
{
///
/// 原来的
diff --git a/Mirai.Net/Data/Events/Concretes/Group/JoinedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/JoinedEvent.cs
index 60899f4..c861b64 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/JoinedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/JoinedEvent.cs
@@ -2,8 +2,14 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class JoinedEvent : EventBase
+///
+/// Bot加入了一个新群
+///
+public record JoinedEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.Joined;
///
diff --git a/Mirai.Net/Data/Events/Concretes/Group/KickedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/KickedEvent.cs
index fafcdd7..e05a504 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/KickedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/KickedEvent.cs
@@ -2,8 +2,14 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class KickedEvent : EventBase
+///
+/// Bot被某群踢了
+///
+public record KickedEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.Kicked;
///
diff --git a/Mirai.Net/Data/Events/Concretes/Group/LeftEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/LeftEvent.cs
index 46fddff..44b13c2 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/LeftEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/LeftEvent.cs
@@ -2,8 +2,14 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class LeftEvent : EventBase
+///
+/// Bot主动离开了某群
+///
+public record LeftEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.Left;
///
diff --git a/Mirai.Net/Data/Events/Concretes/Group/MemberCardChangedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/MemberCardChangedEvent.cs
index 8bd42bd..12c29d3 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/MemberCardChangedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/MemberCardChangedEvent.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class MemberCardChangedEvent : GroupMemberSettingChangedEventBase
+///
+/// 某人的群名片改变
+///
+public record MemberCardChangedEvent : GroupMemberSettingChangedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.MemberCardChanged;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/MemberHonorChangedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/MemberHonorChangedEvent.cs
index 2bf6408..1eb6a49 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/MemberHonorChangedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/MemberHonorChangedEvent.cs
@@ -1,24 +1,44 @@
-using System.ComponentModel;
-using System.Runtime.Serialization;
-using Mirai.Net.Data.Shared;
+using Mirai.Net.Data.Shared;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
+using System.ComponentModel;
+using System.Runtime.Serialization;
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class MemberHonorChangedEvent : EventBase
+///
+/// 群员称号改变
+///
+public record MemberHonorChangedEvent : EventBase
{
+ ///
+ /// 改变类型
+ ///
public enum MemberHonorAction
{
- [EnumMember(Value = "achieve")] [Description("achieve")]
+ ///
+ /// 得到称号
+ ///
+ [EnumMember(Value = "achieve")]
+ [Description("achieve")]
Achieve,
- [EnumMember(Value = "lose")] [Description("lose")]
+ ///
+ /// 失去称号
+ ///
+ [EnumMember(Value = "lose")]
+ [Description("lose")]
Lose
}
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.MemberHonorChanged;
+ ///
+ /// 当事人
+ ///
[JsonProperty("member")] public Member Member { get; set; }
///
diff --git a/Mirai.Net/Data/Events/Concretes/Group/MemberJoinedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/MemberJoinedEvent.cs
index e5fc1b8..30cd4b3 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/MemberJoinedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/MemberJoinedEvent.cs
@@ -3,9 +3,23 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class MemberJoinedEvent : EventBase
+///
+/// 新成员入群
+///
+public record MemberJoinedEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.MemberJoined;
- [JsonProperty("member")] public Member Member { get; set; }
+ ///
+ /// 当事人
+ ///
+ [JsonProperty("member")] public Member Member { get; set; }
+
+ ///
+ /// 肇事者
+ ///
+ [JsonProperty("invitor")] public Member Invitor { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/MemberKickedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/MemberKickedEvent.cs
index 0ea065c..09d5ba7 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/MemberKickedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/MemberKickedEvent.cs
@@ -3,11 +3,23 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class MemberKickedEvent : EventBase
+///
+/// 某群员被踢出群
+///
+public record MemberKickedEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.MemberKicked;
+ ///
+ /// 当事人
+ ///
[JsonProperty("member")] public Member Member { get; set; }
+ ///
+ /// 踢人者
+ ///
[JsonProperty("operator")] public Member Operator { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/MemberLeftEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/MemberLeftEvent.cs
index aa71856..f9810d9 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/MemberLeftEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/MemberLeftEvent.cs
@@ -3,9 +3,18 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class MemberLeftEvent : EventBase
+///
+/// 群成员离开群
+///
+public record MemberLeftEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.MemberLeft;
+ ///
+ /// 当事人
+ ///
[JsonProperty("member")] public Member Member { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/MemberMutedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/MemberMutedEvent.cs
index 79da120..d9b5fec 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/MemberMutedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/MemberMutedEvent.cs
@@ -3,13 +3,28 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class MemberMutedEvent : EventBase
+///
+/// 某群员被禁言
+///
+public record MemberMutedEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.MemberMuted;
- [JsonProperty("durationSeconds")] public string Period { get; set; }
+ ///
+ /// 禁言时长,单位为秒
+ ///
+ [JsonProperty("durationSeconds")] public int Period { get; set; }
+ ///
+ /// 当事人
+ ///
[JsonProperty("Member")] public Member Member { get; set; }
+ ///
+ /// 禁言者
+ ///
[JsonProperty("Operator")] public Member Operator { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/MemberPermissionChangedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/MemberPermissionChangedEvent.cs
index 266f4c4..283a44e 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/MemberPermissionChangedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/MemberPermissionChangedEvent.cs
@@ -2,7 +2,13 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class MemberPermissionChangedEvent : GroupMemberSettingChangedEventBase
+///
+/// 某群员权限改变,操作者一定是群主
+///
+public record MemberPermissionChangedEvent : GroupMemberSettingChangedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.MemberPermissionChanged;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/MemberTitleChangedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/MemberTitleChangedEvent.cs
index 0995d3a..1b71a9a 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/MemberTitleChangedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/MemberTitleChangedEvent.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class MemberTitleChangedEvent : GroupMemberSettingChangedEventBase
+///
+/// 群头衔改动(只有群主有操作限权)
+///
+public record MemberTitleChangedEvent : GroupMemberSettingChangedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.MemberTitleChanged;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/MemberUnmutedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/MemberUnmutedEvent.cs
index cb60a99..1d83a5e 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/MemberUnmutedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/MemberUnmutedEvent.cs
@@ -3,11 +3,23 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class MemberUnmutedEvent : EventBase
+///
+/// 群员被解除禁言
+///
+public record MemberUnmutedEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.MemberUnmuted;
+ ///
+ /// 当事人
+ ///
[JsonProperty("Member")] public Member Member { get; set; }
+ ///
+ /// 解除禁言的人
+ ///
[JsonProperty("Operator")] public Member Operator { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/MutedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/MutedEvent.cs
index 678966c..ee6f30f 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/MutedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/MutedEvent.cs
@@ -3,8 +3,14 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class MutedEvent : EventBase
+///
+/// Bot被禁言
+///
+public record MutedEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.Muted;
///
diff --git a/Mirai.Net/Data/Events/Concretes/Group/PermissionChangedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/PermissionChangedEvent.cs
index 7eaec96..55d8066 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/PermissionChangedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/PermissionChangedEvent.cs
@@ -4,17 +4,32 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class PermissionChangedEvent : EventBase
+///
+/// Bot在群内的权限改变,操作者一定是群主
+///
+public record PermissionChangedEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.PermissionChanged;
+ ///
+ /// 原来的权限
+ ///
[JsonProperty("origin")]
[JsonConverter(typeof(StringEnumConverter))]
public Permissions Origin { get; set; }
+ ///
+ /// 目前的权限
+ ///
[JsonProperty("current")]
[JsonConverter(typeof(StringEnumConverter))]
public Permissions Current { get; set; }
+ ///
+ /// 事发群
+ ///
[JsonProperty("group")] public Shared.Group Group { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Group/UnmutedEvent.cs b/Mirai.Net/Data/Events/Concretes/Group/UnmutedEvent.cs
index 2640dda..d39fdff 100644
--- a/Mirai.Net/Data/Events/Concretes/Group/UnmutedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Group/UnmutedEvent.cs
@@ -3,8 +3,14 @@
namespace Mirai.Net.Data.Events.Concretes.Group;
-public class UnmutedEvent : EventBase
+///
+/// Bot被解除禁言
+///
+public record UnmutedEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.Unmuted;
///
diff --git a/Mirai.Net/Data/Events/Concretes/Message/AtEvent.cs b/Mirai.Net/Data/Events/Concretes/Message/AtEvent.cs
index d887936..a1c499a 100644
--- a/Mirai.Net/Data/Events/Concretes/Message/AtEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Message/AtEvent.cs
@@ -1,11 +1,19 @@
using Mirai.Net.Data.Messages.Receivers;
-using Mirai.Net.Data.Shared;
namespace Mirai.Net.Data.Events.Concretes.Message;
-public class AtEvent : EventBase
+///
+/// Bot被人at
+///
+public record AtEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.At;
+ ///
+ /// 被at的那条消息容器
+ ///
public GroupMessageReceiver Receiver { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Message/NudgeEvent.cs b/Mirai.Net/Data/Events/Concretes/Message/NudgeEvent.cs
index 97ccc17..4b1677c 100644
--- a/Mirai.Net/Data/Events/Concretes/Message/NudgeEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Message/NudgeEvent.cs
@@ -2,24 +2,54 @@
namespace Mirai.Net.Data.Events.Concretes.Message;
-public class NudgeEvent : EventBase
+///
+/// 某人被戳了一戳
+///
+public record NudgeEvent : EventBase
{
+ ///
+ /// 是谁戳的
+ ///
[JsonProperty("fromId")] public string FromId { get; set; }
+ ///
+ /// 谁被戳了
+ ///
[JsonProperty("target")] public string Target { get; set; }
+ ///
+ /// 怎么戳的
+ ///
[JsonProperty("action")] public string Action { get; set; }
+ ///
+ /// 自定义的怎么戳
+ ///
[JsonProperty("suffix")] public string Suffix { get; set; }
+ ///
+ /// 来源
+ ///
[JsonProperty("subject")] public NudgeSubject Subject { get; set; }
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.Nudged;
+ ///
+ /// 来源
+ ///
public class NudgeSubject
{
+ ///
+ /// 来源的QQ号(好友)或群号
+ ///
[JsonProperty("id")] public string Id { get; set; }
+ ///
+ /// 来源的类型,"Friend"或"Group"
+ ///
[JsonProperty("kind")] public string Kind { get; set; }
}
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/OtherClient/OtherClientOfflineEvent.cs b/Mirai.Net/Data/Events/Concretes/OtherClient/OtherClientOfflineEvent.cs
index 7ff2416..13fbcf9 100644
--- a/Mirai.Net/Data/Events/Concretes/OtherClient/OtherClientOfflineEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/OtherClient/OtherClientOfflineEvent.cs
@@ -2,10 +2,19 @@
namespace Mirai.Net.Data.Events.Concretes.OtherClient;
-public class OtherClientOfflineEvent : EventBase
+///
+/// 其它客户端离线
+///
+public record OtherClientOfflineEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.OtherClientOffline;
-
+
+ ///
+ /// 啥客户端
+ ///
[JsonProperty("client")]
- public Shared.OtherClient Client {get; set;}
+ public Shared.OtherClient Client { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/OtherClient/OtherClientOnlineEvent.cs b/Mirai.Net/Data/Events/Concretes/OtherClient/OtherClientOnlineEvent.cs
index 91e0b11..daf750c 100644
--- a/Mirai.Net/Data/Events/Concretes/OtherClient/OtherClientOnlineEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/OtherClient/OtherClientOnlineEvent.cs
@@ -2,13 +2,25 @@
namespace Mirai.Net.Data.Events.Concretes.OtherClient;
-public class OtherClientOnlineEvent : EventBase
+///
+/// 其它客户端上线
+///
+public record OtherClientOnlineEvent : EventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.OtherClientOnline;
+ ///
+ /// 啥客户端
+ ///
[JsonProperty("client")]
public Shared.OtherClient Client { get; set; }
-
+
+ ///
+ /// 详细设备类型
+ ///
[JsonProperty("kind")]
- public string Kind {get; set;}
+ public long Kind { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Request/NewFriendRequestedEvent.cs b/Mirai.Net/Data/Events/Concretes/Request/NewFriendRequestedEvent.cs
index b63d89a..f844784 100644
--- a/Mirai.Net/Data/Events/Concretes/Request/NewFriendRequestedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Request/NewFriendRequestedEvent.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Events.Concretes.Request;
-public class NewFriendRequestedEvent : RequestedEventBase
+///
+/// 新的好友请求
+///
+public record NewFriendRequestedEvent : RequestedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.NewFriendRequested;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Request/NewInvitationRequestedEvent.cs b/Mirai.Net/Data/Events/Concretes/Request/NewInvitationRequestedEvent.cs
index 516b0b1..7f83e8f 100644
--- a/Mirai.Net/Data/Events/Concretes/Request/NewInvitationRequestedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Request/NewInvitationRequestedEvent.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Events.Concretes.Request;
-public class NewInvitationRequestedEvent : RequestedEventBase
+///
+/// 新的邀请(邀请bot加入某群)
+///
+public record NewInvitationRequestedEvent : RequestedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.NewInvitationRequested;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Request/NewMemberRequestedEvent.cs b/Mirai.Net/Data/Events/Concretes/Request/NewMemberRequestedEvent.cs
index 88c2867..609035b 100644
--- a/Mirai.Net/Data/Events/Concretes/Request/NewMemberRequestedEvent.cs
+++ b/Mirai.Net/Data/Events/Concretes/Request/NewMemberRequestedEvent.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Events.Concretes.Request;
-public class NewMemberRequestedEvent : RequestedEventBase
+///
+/// 新成员申请
+///
+public record NewMemberRequestedEvent : RequestedEventBase
{
+ ///
+ /// 事件类型
+ ///
public override Events Type { get; set; } = Events.NewMemberRequested;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/Request/RequestedEventBase.cs b/Mirai.Net/Data/Events/Concretes/Request/RequestedEventBase.cs
index 1396279..0df65f2 100644
--- a/Mirai.Net/Data/Events/Concretes/Request/RequestedEventBase.cs
+++ b/Mirai.Net/Data/Events/Concretes/Request/RequestedEventBase.cs
@@ -2,15 +2,33 @@
namespace Mirai.Net.Data.Events.Concretes.Request;
-public abstract class RequestedEventBase : EventBase
+///
+/// 请求事件基类
+///
+public record class RequestedEventBase : EventBase
{
+ ///
+ /// 事件id
+ ///
[JsonProperty("eventId")] public string EventId { get; set; }
+ ///
+ /// 来自谁
+ ///
[JsonProperty("fromId")] public string FromId { get; set; }
+ ///
+ /// 群号
+ ///
[JsonProperty("groupId")] public string GroupId { get; set; }
+ ///
+ /// 昵称
+ ///
[JsonProperty("nick")] public string Nick { get; set; }
+ ///
+ /// 附加消息
+ ///
[JsonProperty("message")] public string Message { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Concretes/UnknownEvent.cs b/Mirai.Net/Data/Events/Concretes/UnknownEvent.cs
new file mode 100644
index 0000000..c6cc438
--- /dev/null
+++ b/Mirai.Net/Data/Events/Concretes/UnknownEvent.cs
@@ -0,0 +1,36 @@
+using Newtonsoft.Json;
+
+namespace Mirai.Net.Data.Events.Concretes;
+
+///
+/// 未知的事件
+///
+public record UnknownEvent : EventBase
+{
+ ///
+ ///
+ ///
+ [JsonIgnore] public override Events Type { get; set; } = Events.Unknown;
+
+ ///
+ /// 原json
+ ///
+ [JsonIgnore]
+ public string RawJson { get; set; }
+
+ ///
+ ///
+ ///
+ public UnknownEvent()
+ {
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public UnknownEvent(string rawJson)
+ {
+ RawJson = rawJson;
+ }
+}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/EventBase.cs b/Mirai.Net/Data/Events/EventBase.cs
index 511a9e7..d71c91e 100644
--- a/Mirai.Net/Data/Events/EventBase.cs
+++ b/Mirai.Net/Data/Events/EventBase.cs
@@ -1,19 +1,32 @@
-using AHpx.Extensions.StringExtensions;
+using Manganese.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Mirai.Net.Data.Events;
-public class EventBase
+///
+/// 事件基类
+///
+public record EventBase
{
+ ///
+ /// 你又看不到这个
+ ///
protected EventBase()
{
}
+ ///
+ /// 事件类型
+ ///
[JsonProperty("type")]
[JsonConverter(typeof(StringEnumConverter))]
public virtual Events Type { get; set; }
+ ///
+ /// ToString实际上是ToJsonString也就是说会被序列化成JSON文本
+ ///
+ ///
public override string ToString()
{
return this.ToJsonString();
diff --git a/Mirai.Net/Data/Events/EventTargets.cs b/Mirai.Net/Data/Events/EventTargets.cs
deleted file mode 100644
index 36fdfe1..0000000
--- a/Mirai.Net/Data/Events/EventTargets.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Mirai.Net.Data.Events;
-
-public enum EventTargets
-{
- Bot,
- Friend,
- Group,
- Request
-}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Events/Events.cs b/Mirai.Net/Data/Events/Events.cs
index 81ddf2b..ae3077f 100644
--- a/Mirai.Net/Data/Events/Events.cs
+++ b/Mirai.Net/Data/Events/Events.cs
@@ -3,221 +3,286 @@
namespace Mirai.Net.Data.Events;
+///
+/// 事件类型
+///
public enum Events
{
///
/// Bot登录成功
///
- [Description("BotOnlineEvent")] [EnumMember(Value = "BotOnlineEvent")]
+ [Description("BotOnlineEvent")]
+ [EnumMember(Value = "BotOnlineEvent")]
Online,
///
/// Bot主动离线
///
- [Description("BotOfflineEventActive")] [EnumMember(Value = "BotOfflineEventActive")]
+ [Description("BotOfflineEventActive")]
+ [EnumMember(Value = "BotOfflineEventActive")]
Offline,
///
/// Bot被挤下线
///
- [Description("BotOfflineEventForce")] [EnumMember(Value = "BotOfflineEventForce")]
+ [Description("BotOfflineEventForce")]
+ [EnumMember(Value = "BotOfflineEventForce")]
OfflineForce,
///
/// Bot被服务器断开或因网络问题而掉线
///
- [Description("BotOfflineEventDropped")] [EnumMember(Value = "BotOfflineEventDropped")]
+ [Description("BotOfflineEventDropped")]
+ [EnumMember(Value = "BotOfflineEventDropped")]
Dropped,
///
/// Bot主动重新登录
///
- [Description("BotReloginEvent")] [EnumMember(Value = "BotReloginEvent")]
+ [Description("BotReloginEvent")]
+ [EnumMember(Value = "BotReloginEvent")]
Reconnected,
///
/// 好友输入状态改变
///
- [Description("FriendInputStatusChangedEvent")] [EnumMember(Value = "FriendInputStatusChangedEvent")]
+ [Description("FriendInputStatusChangedEvent")]
+ [EnumMember(Value = "FriendInputStatusChangedEvent")]
FriendInputStatusChanged,
///
/// 好友昵称改变
///
- [Description("FriendNickChangedEvent")] [EnumMember(Value = "FriendNickChangedEvent")]
+ [Description("FriendNickChangedEvent")]
+ [EnumMember(Value = "FriendNickChangedEvent")]
FriendNickChanged,
///
/// Bot在群里的权限被改变. 操作人一定是群主
///
- [Description("BotGroupPermissionChangeEvent")] [EnumMember(Value = "BotGroupPermissionChangeEvent")]
+ [Description("BotGroupPermissionChangeEvent")]
+ [EnumMember(Value = "BotGroupPermissionChangeEvent")]
PermissionChanged,
///
/// Bot被禁言
///
- [Description("BotMuteEvent")] [EnumMember(Value = "BotMuteEvent")]
+ [Description("BotMuteEvent")]
+ [EnumMember(Value = "BotMuteEvent")]
Muted,
///
/// Bot被取消禁言
///
- [Description("BotUnmuteEvent")] [EnumMember(Value = "BotUnmuteEvent")]
+ [Description("BotUnmuteEvent")]
+ [EnumMember(Value = "BotUnmuteEvent")]
Unmuted,
///
/// Bot加入了一个新群
///
- [Description("BotJoinGroupEvent")] [EnumMember(Value = "BotJoinGroupEvent")]
+ [Description("BotJoinGroupEvent")]
+ [EnumMember(Value = "BotJoinGroupEvent")]
Joined,
///
/// Bot主动退出一个群
///
- [Description("BotLeaveEventActive")] [EnumMember(Value = "BotLeaveEventActive")]
+ [Description("BotLeaveEventActive")]
+ [EnumMember(Value = "BotLeaveEventActive")]
Left,
///
/// Bot被踢出一个群
///
- [Description("BotLeaveEventKick")] [EnumMember(Value = "BotLeaveEventKick")]
- Kicked,
+ [Description("BotLeaveEventKick")]
+ [EnumMember(Value = "BotLeaveEventKick")]
+ Kicked,
+
+ ///
+ /// Bot因群主解散群而退出群
+ ///
+ [Description("BotLeaveEventDisband")]
+ [EnumMember(Value = "BotLeaveEventDisband")]
+ Disbanded,
///
/// 群消息撤回
///
- [Description("GroupRecallEvent")] [EnumMember(Value = "GroupRecallEvent")]
+ [Description("GroupRecallEvent")]
+ [EnumMember(Value = "GroupRecallEvent")]
GroupMessageRecalled,
///
/// 好友消息撤回
///
- [Description("FriendRecallEvent")] [EnumMember(Value = "FriendRecallEvent")]
+ [Description("FriendRecallEvent")]
+ [EnumMember(Value = "FriendRecallEvent")]
FriendRecalled,
///
/// 某个群名改变
///
- [Description("GroupNameChangeEvent")] [EnumMember(Value = "GroupNameChangeEvent")]
+ [Description("GroupNameChangeEvent")]
+ [EnumMember(Value = "GroupNameChangeEvent")]
GroupNameChanged,
///
/// 某群入群公告改变
///
- [Description("GroupEntranceAnnouncementChangeEvent")] [EnumMember(Value = "GroupEntranceAnnouncementChangeEvent")]
+ [Description("GroupEntranceAnnouncementChangeEvent")]
+ [EnumMember(Value = "GroupEntranceAnnouncementChangeEvent")]
GroupEntranceAnnouncementChanged,
///
/// 全员禁言
///
- [Description("GroupMuteAllEvent")] [EnumMember(Value = "GroupMuteAllEvent")]
+ [Description("GroupMuteAllEvent")]
+ [EnumMember(Value = "GroupMuteAllEvent")]
GroupMutedAll,
///
/// 匿名聊天
///
- [Description("GroupAllowAnonymousChatEvent")] [EnumMember(Value = "GroupAllowAnonymousChatEvent")]
+ [Description("GroupAllowAnonymousChatEvent")]
+ [EnumMember(Value = "GroupAllowAnonymousChatEvent")]
GroupAllowedAnonymousChat,
///
/// 坦白说
///
- [Description("GroupAllowConfessTalkEvent")] [EnumMember(Value = "GroupAllowConfessTalkEvent")]
+ [Description("GroupAllowConfessTalkEvent")]
+ [EnumMember(Value = "GroupAllowConfessTalkEvent")]
GroupAllowedConfessTalk,
///
/// 允许群员邀请好友加群
///
- [Description("GroupAllowMemberInviteEvent")] [EnumMember(Value = "GroupAllowMemberInviteEvent")]
+ [Description("GroupAllowMemberInviteEvent")]
+ [EnumMember(Value = "GroupAllowMemberInviteEvent")]
GroupAllowedMemberInvite,
///
/// 新人入群的事件
///
- [Description("MemberJoinEvent")] [EnumMember(Value = "MemberJoinEvent")]
+ [Description("MemberJoinEvent")]
+ [EnumMember(Value = "MemberJoinEvent")]
MemberJoined,
///
/// 成员被踢出群(该成员不是Bot)
///
- [Description("MemberLeaveEventKick")] [EnumMember(Value = "MemberLeaveEventKick")]
+ [Description("MemberLeaveEventKick")]
+ [EnumMember(Value = "MemberLeaveEventKick")]
MemberKicked,
///
/// 成员主动离群(该成员不是Bot)
///
- [Description("MemberLeaveEventQuit")] [EnumMember(Value = "MemberLeaveEventQuit")]
+ [Description("MemberLeaveEventQuit")]
+ [EnumMember(Value = "MemberLeaveEventQuit")]
MemberLeft,
///
/// 群名片改动
///
- [Description("MemberCardChangeEvent")] [EnumMember(Value = "MemberCardChangeEvent")]
+ [Description("MemberCardChangeEvent")]
+ [EnumMember(Value = "MemberCardChangeEvent")]
MemberCardChanged,
///
/// 群头衔改动(只有群主有操作限权)
///
- [Description("MemberSpecialTitleChangeEvent")] [EnumMember(Value = "MemberSpecialTitleChangeEvent")]
+ [Description("MemberSpecialTitleChangeEvent")]
+ [EnumMember(Value = "MemberSpecialTitleChangeEvent")]
MemberTitleChanged,
///
/// 成员权限改变的事件(该成员不是Bot)
///
- [Description("MemberPermissionChangeEvent")] [EnumMember(Value = "MemberPermissionChangeEvent")]
+ [Description("MemberPermissionChangeEvent")]
+ [EnumMember(Value = "MemberPermissionChangeEvent")]
MemberPermissionChanged,
///
/// 群成员被禁言事件(该成员不是Bot)
///
- [Description("MemberMuteEvent")] [EnumMember(Value = "MemberMuteEvent")]
+ [Description("MemberMuteEvent")]
+ [EnumMember(Value = "MemberMuteEvent")]
MemberMuted,
///
/// 群成员被取消禁言事件(该成员不是Bot)
///
- [Description("MemberUnmuteEvent")] [EnumMember(Value = "MemberUnmuteEvent")]
+ [Description("MemberUnmuteEvent")]
+ [EnumMember(Value = "MemberUnmuteEvent")]
MemberUnmuted,
///
/// 群员称号改变
///
- [Description("MemberHonorChangeEvent")] [EnumMember(Value = "MemberHonorChangeEvent")]
+ [Description("MemberHonorChangeEvent")]
+ [EnumMember(Value = "MemberHonorChangeEvent")]
MemberHonorChanged,
///
/// 添加好友申请
///
- [Description("NewFriendRequestEvent")] [EnumMember(Value = "NewFriendRequestEvent")]
+ [Description("NewFriendRequestEvent")]
+ [EnumMember(Value = "NewFriendRequestEvent")]
NewFriendRequested,
///
/// 用户入群申请(Bot需要有管理员权限)
///
- [Description("MemberJoinRequestEvent")] [EnumMember(Value = "MemberJoinRequestEvent")]
+ [Description("MemberJoinRequestEvent")]
+ [EnumMember(Value = "MemberJoinRequestEvent")]
NewMemberRequested,
///
/// Bot被邀请入群申请
///
- [Description("BotInvitedJoinGroupRequestEvent")] [EnumMember(Value = "BotInvitedJoinGroupRequestEvent")]
+ [Description("BotInvitedJoinGroupRequestEvent")]
+ [EnumMember(Value = "BotInvitedJoinGroupRequestEvent")]
NewInvitationRequested,
///
/// 戳一戳事件
///
- [Description("NudgeEvent")] [EnumMember(Value = "NudgeEvent")]
+ [Description("NudgeEvent")]
+ [EnumMember(Value = "NudgeEvent")]
Nudged,
-
+
+ ///
+ /// 其他客户端登录
+ ///
[Description("OtherClientOnlineEvent")]
[EnumMember(Value = "OtherClientOnlineEvent")]
OtherClientOnline,
-
+
+ ///
+ /// 其他客户端离线
+ ///
[Description("OtherClientOfflineEvent")]
[EnumMember(Value = "OtherClientOfflineEvent")]
OtherClientOffline,
-
+
+ ///
+ /// bot被at
+ ///
[Description("At")]
[EnumMember(Value = "At")]
- At
+ At,
+
+ ///
+ /// 命令被执行
+ ///
+ [Description("CommandExecutedEvent")]
+ [EnumMember(Value = "CommandExecutedEvent")]
+ CommandExecuted,
+
+ ///
+ /// 未知类型的事件
+ ///
+ Unknown
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Exceptions/InvalidAddressException.cs b/Mirai.Net/Data/Exceptions/InvalidAddressException.cs
index da3eebb..a3bb286 100644
--- a/Mirai.Net/Data/Exceptions/InvalidAddressException.cs
+++ b/Mirai.Net/Data/Exceptions/InvalidAddressException.cs
@@ -16,19 +16,19 @@ public class InvalidAddressException : Exception
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
//
- public InvalidAddressException()
+ internal InvalidAddressException()
{
}
- public InvalidAddressException(string message) : base(message)
+ internal InvalidAddressException(string message) : base(message)
{
}
- public InvalidAddressException(string message, Exception inner) : base(message, inner)
+ internal InvalidAddressException(string message, Exception inner) : base(message, inner)
{
}
- protected InvalidAddressException(
+ internal InvalidAddressException(
SerializationInfo info,
StreamingContext context) : base(info, context)
{
diff --git a/Mirai.Net/Data/Exceptions/InvalidCommandEntityException.cs b/Mirai.Net/Data/Exceptions/InvalidCommandEntityException.cs
deleted file mode 100644
index 13b72ed..0000000
--- a/Mirai.Net/Data/Exceptions/InvalidCommandEntityException.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Mirai.Net.Data.Exceptions;
-
-[Serializable]
-public class InvalidCommandEntityException : Exception
-{
- //
- // For guidelines regarding the creation of new exception types, see
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
- // and
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
- //
-
- public InvalidCommandEntityException()
- {
- }
-
- public InvalidCommandEntityException(string message) : base(message)
- {
- }
-
- public InvalidCommandEntityException(string message, Exception inner) : base(message, inner)
- {
- }
-
- protected InvalidCommandEntityException(
- SerializationInfo info,
- StreamingContext context) : base(info, context)
- {
- }
-}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Exceptions/InvalidCommandException.cs b/Mirai.Net/Data/Exceptions/InvalidCommandException.cs
deleted file mode 100644
index cb96139..0000000
--- a/Mirai.Net/Data/Exceptions/InvalidCommandException.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Mirai.Net.Data.Exceptions;
-
-[Serializable]
-public class InvalidCommandException : Exception
-{
- //
- // For guidelines regarding the creation of new exception types, see
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
- // and
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
- //
-
- public InvalidCommandException()
- {
- }
-
- public InvalidCommandException(string message) : base(message)
- {
- }
-
- public InvalidCommandException(string message, Exception inner) : base(message, inner)
- {
- }
-
- protected InvalidCommandException(
- SerializationInfo info,
- StreamingContext context) : base(info, context)
- {
- }
-}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Exceptions/InvalidQQException.cs b/Mirai.Net/Data/Exceptions/InvalidQQException.cs
index 35bb8df..0c9258f 100644
--- a/Mirai.Net/Data/Exceptions/InvalidQQException.cs
+++ b/Mirai.Net/Data/Exceptions/InvalidQQException.cs
@@ -16,19 +16,19 @@ public class InvalidQQException : Exception
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
//
- public InvalidQQException()
+ internal InvalidQQException()
{
}
- public InvalidQQException(string message) : base(message)
+ internal InvalidQQException(string message) : base(message)
{
}
- public InvalidQQException(string message, Exception inner) : base(message, inner)
+ internal InvalidQQException(string message, Exception inner) : base(message, inner)
{
}
- protected InvalidQQException(
+ internal InvalidQQException(
SerializationInfo info,
StreamingContext context) : base(info, context)
{
diff --git a/Mirai.Net/Data/Exceptions/InvalidResponseException.cs b/Mirai.Net/Data/Exceptions/InvalidResponseException.cs
index cc38705..9ae935d 100644
--- a/Mirai.Net/Data/Exceptions/InvalidResponseException.cs
+++ b/Mirai.Net/Data/Exceptions/InvalidResponseException.cs
@@ -3,6 +3,9 @@
namespace Mirai.Net.Data.Exceptions;
+///
+/// 错误的响应
+///
[Serializable]
public class InvalidResponseException : Exception
{
@@ -13,19 +16,19 @@ public class InvalidResponseException : Exception
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
//
- public InvalidResponseException()
+ internal InvalidResponseException()
{
}
- public InvalidResponseException(string message) : base(message)
+ internal InvalidResponseException(string message) : base(message)
{
}
- public InvalidResponseException(string message, Exception inner) : base(message, inner)
+ internal InvalidResponseException(string message, Exception inner) : base(message, inner)
{
}
- protected InvalidResponseException(
+ internal InvalidResponseException(
SerializationInfo info,
StreamingContext context) : base(info, context)
{
diff --git a/Mirai.Net/Data/Exceptions/InvalidWebsocketReponseException.cs b/Mirai.Net/Data/Exceptions/InvalidWebsocketReponseException.cs
new file mode 100644
index 0000000..f1a9da3
--- /dev/null
+++ b/Mirai.Net/Data/Exceptions/InvalidWebsocketReponseException.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Mirai.Net.Data.Exceptions;
+
+///
+///
+///
+[Serializable]
+public class InvalidWebsocketReponseException : Exception
+{
+ //
+ // For guidelines regarding the creation of new exception types, see
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
+ // and
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
+ //
+
+ ///
+ ///
+ ///
+ public InvalidWebsocketReponseException()
+ {
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public InvalidWebsocketReponseException(string message) : base(message)
+ {
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public InvalidWebsocketReponseException(string message, Exception inner) : base(message, inner)
+ {
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected InvalidWebsocketReponseException(
+ SerializationInfo info,
+ StreamingContext context) : base(info, context)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/AppMessage.cs b/Mirai.Net/Data/Messages/Concretes/AppMessage.cs
index cbb7c33..b490936 100644
--- a/Mirai.Net/Data/Messages/Concretes/AppMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/AppMessage.cs
@@ -2,9 +2,18 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class AppMessage : MessageBase
+///
+/// 小程序消息
+///
+public record AppMessage : MessageBase
{
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.App;
- [JsonProperty("app")] public string App { get; set; }
+ ///
+ /// 消息内容
+ ///
+ [JsonProperty("content")] public string Content { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/AtAllMessage.cs b/Mirai.Net/Data/Messages/Concretes/AtAllMessage.cs
index eadb569..9271dd8 100644
--- a/Mirai.Net/Data/Messages/Concretes/AtAllMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/AtAllMessage.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class AtAllMessage : MessageBase
+///
+/// @全体成员
+///
+public record AtAllMessage : MessageBase
{
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.AtAll;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/AtMessage.cs b/Mirai.Net/Data/Messages/Concretes/AtMessage.cs
index fbcf1a7..a536063 100644
--- a/Mirai.Net/Data/Messages/Concretes/AtMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/AtMessage.cs
@@ -1,14 +1,34 @@
-using Newtonsoft.Json;
+using Mirai.Net.Data.Shared;
+using Newtonsoft.Json;
namespace Mirai.Net.Data.Messages.Concretes;
-public class AtMessage : MessageBase
+///
+/// @某人
+///
+public record AtMessage : MessageBase
{
+ ///
+ /// 带参数的构造器
+ ///
+ /// 要@的人的qq
public AtMessage(string target)
{
Target = target;
}
+ ///
+ ///
+ ///
+ ///
+ public AtMessage(Member target)
+ {
+ Target = target.Id;
+ }
+
+ ///
+ ///
+ ///
public AtMessage()
{
}
@@ -23,7 +43,10 @@ public AtMessage()
/// At时显示的文字,发送消息时无效,自动使用群名片,默认为空
///
[JsonProperty("display")]
- public string Display { get; set; } = "";
+ internal string Display { get; set; } = "";
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.At;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/DiceMessage.cs b/Mirai.Net/Data/Messages/Concretes/DiceMessage.cs
index cb96d85..5b61eba 100644
--- a/Mirai.Net/Data/Messages/Concretes/DiceMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/DiceMessage.cs
@@ -2,8 +2,14 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class DiceMessage : MessageBase
+///
+/// 骰子消息
+///
+public record DiceMessage : MessageBase
{
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.Dice;
///
diff --git a/Mirai.Net/Data/Messages/Concretes/FaceMessage.cs b/Mirai.Net/Data/Messages/Concretes/FaceMessage.cs
index 81aa1a8..5c68968 100644
--- a/Mirai.Net/Data/Messages/Concretes/FaceMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/FaceMessage.cs
@@ -2,10 +2,13 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class FaceMessage : MessageBase
+///
+/// qq表情
+///
+public record FaceMessage : MessageBase
{
///
- /// QQ表情编号,可选,优先高于name
+ /// QQ表情编号,可选,优先高于
///
[JsonProperty("faceId")]
public string FaceId { get; set; }
@@ -16,5 +19,8 @@ public class FaceMessage : MessageBase
[JsonProperty("name")]
public string Name { get; set; }
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.Face;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/FileMessage.cs b/Mirai.Net/Data/Messages/Concretes/FileMessage.cs
index 3d45ebf..5dfc2f4 100644
--- a/Mirai.Net/Data/Messages/Concretes/FileMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/FileMessage.cs
@@ -2,8 +2,14 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class FileMessage : MessageBase
+///
+/// 文件
+///
+public record FileMessage : MessageBase
{
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.File;
///
diff --git a/Mirai.Net/Data/Messages/Concretes/FlashImageMessage.cs b/Mirai.Net/Data/Messages/Concretes/FlashImageMessage.cs
index ce8acb5..3c7cbfd 100644
--- a/Mirai.Net/Data/Messages/Concretes/FlashImageMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/FlashImageMessage.cs
@@ -1,6 +1,12 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class FlashImageMessage : ImageMessage
+///
+/// 闪照,构造方式与相同
+///
+public record FlashImageMessage : ImageMessage
{
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.FlashImage;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/ForwardMessage.cs b/Mirai.Net/Data/Messages/Concretes/ForwardMessage.cs
index a367ff6..ff807d1 100644
--- a/Mirai.Net/Data/Messages/Concretes/ForwardMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/ForwardMessage.cs
@@ -1,19 +1,60 @@
-using System.Collections.Generic;
-using Newtonsoft.Json;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace Mirai.Net.Data.Messages.Concretes;
-public class ForwardMessage : MessageBase
+///
+/// 转发的消息
+///
+public record ForwardMessage : MessageBase
{
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.Forward;
+ ///
+ /// 点进消息前的显示内容
+ ///
+ [JsonProperty("display")]
+ public ForwardDisplay Display { get; set; }
+
///
/// 消息节点
///
[JsonProperty("nodeList")]
public IEnumerable NodeList { get; set; }
- public class ForwardNode
+ ///
+ /// 从单个人的消息中构建转发消息
+ ///
+ /// 某人的id
+ /// 某人的昵称
+ /// 消息链的集合,每个消息链就是一条消息
+ ///
+ public static ForwardMessage FromChains(string id, string name, IEnumerable chains)
+ {
+ var re = new ForwardMessage
+ {
+ NodeList = chains.Select(c => new ForwardNode
+ {
+ SenderId = id,
+ SenderName = name,
+ Time = DateTimeOffset.Now.ToUnixTimeSeconds().ToString(),
+ MessageChain = c,
+ SourceId = "114514"
+ })
+ };
+
+ return re;
+ }
+
+ ///
+ /// 转发的消息节点
+ ///
+ public record ForwardNode
{
///
/// 发送人QQ号
@@ -37,7 +78,7 @@ public class ForwardNode
/// 消息数组
///
[JsonProperty("messageChain")]
- public IEnumerable MessageChain { get; set; }
+ public MessageChain MessageChain { get; set; }
///
/// 可以只使用消息messageId,从缓存中读取一条消息作为节点
@@ -45,4 +86,67 @@ public class ForwardNode
[JsonProperty("sourceId")]
public string SourceId { get; set; }
}
+
+ ///
+ /// 未进入转发消息时的显示内容
+ ///
+ public record ForwardDisplay
+ {
+ ///
+ ///
+ ///
+ public ForwardDisplay()
+ {}
+
+ ///
+ /// 生成转发消息的外层显示
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ForwardDisplay(string title = default, string brief = default, string source = default, IEnumerable preview = default, string summary = default)
+ {
+ this.Title = title;
+
+ this.Brief = brief;
+
+ this.Source = source;
+
+ this.Preview = preview;
+
+ this.Summary = summary;
+ }
+
+ ///
+ /// 标题
+ ///
+ [JsonProperty("title")]
+ public string Title { get; set; }
+
+ ///
+ /// 在未进入聊天页面时所产生的消息提示
+ ///
+ [JsonProperty("brief")]
+ public string Brief { get; set; }
+
+ ///
+ /// 目前未发现在哪能显示,建议不填
+ ///
+ [JsonProperty("source")]
+ public string Source { get; set; }
+
+ ///
+ /// 消息内容预览
+ ///
+ [JsonProperty("preview")]
+ public IEnumerable Preview { get; set; }
+
+ ///
+ /// 消息总结
+ ///
+ [JsonProperty("summary")]
+ public string Summary { get; set; }
+ }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/ImageMessage.cs b/Mirai.Net/Data/Messages/Concretes/ImageMessage.cs
index 9629ed9..9a54c9e 100644
--- a/Mirai.Net/Data/Messages/Concretes/ImageMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/ImageMessage.cs
@@ -2,8 +2,14 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class ImageMessage : MessageBase
+///
+/// 图片
+///
+public record ImageMessage : MessageBase
{
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.Image;
///
@@ -29,4 +35,16 @@ public class ImageMessage : MessageBase
///
[JsonProperty("base64")]
public string Base64 { get; set; }
+
+ ///
+ /// 图片的宽度
+ ///
+ [JsonProperty("width")]
+ public string Width { get; set; }
+
+ ///
+ /// 图片的高度
+ ///
+ [JsonProperty("height")]
+ public string Height { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/JsonMessage.cs b/Mirai.Net/Data/Messages/Concretes/JsonMessage.cs
index cc88c63..121d5cd 100644
--- a/Mirai.Net/Data/Messages/Concretes/JsonMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/JsonMessage.cs
@@ -2,9 +2,16 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class JsonMessage : MessageBase
+///
+/// json消息
+///
+public record JsonMessage : MessageBase
{
+ ///json文本
[JsonProperty("json")] public string Json { get; set; }
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.Json;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/MarketFaceMessage.cs b/Mirai.Net/Data/Messages/Concretes/MarketFaceMessage.cs
new file mode 100644
index 0000000..a5e926a
--- /dev/null
+++ b/Mirai.Net/Data/Messages/Concretes/MarketFaceMessage.cs
@@ -0,0 +1,27 @@
+using Newtonsoft.Json;
+
+namespace Mirai.Net.Data.Messages.Concretes;
+
+///
+/// 商城表情
+/// 目前商城表情仅支持接收和转发,不支持构造发送
+///
+public record MarketFaceMessage : MessageBase
+{
+ ///
+ /// 消息类型
+ ///
+ public override Messages Type { get; set; } = Messages.MarketFace;
+
+ ///
+ /// 表情id
+ ///
+ [JsonProperty("id")]
+ public string Id { get; set; }
+
+ ///
+ /// 表情名称
+ ///
+ [JsonProperty("name")]
+ public string Name { get; set; }
+}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/MiraiCodeMessage.cs b/Mirai.Net/Data/Messages/Concretes/MiraiCodeMessage.cs
new file mode 100644
index 0000000..bc7b6c7
--- /dev/null
+++ b/Mirai.Net/Data/Messages/Concretes/MiraiCodeMessage.cs
@@ -0,0 +1,37 @@
+using Newtonsoft.Json;
+
+namespace Mirai.Net.Data.Messages.Concretes;
+
+///
+/// Mirai码,
+/// 看这里
+///
+public record MiraiCodeMessage : MessageBase
+{
+ ///
+ /// 消息类型
+ ///
+ public override Messages Type { get; set; } = Messages.MiraiCode;
+
+ ///
+ /// MiraiCode码,请确保已经转义
+ ///
+ [JsonProperty("code")]
+ public string Code { get; set; }
+
+ ///
+ /// 带参数的构造器
+ ///
+ ///
+ public MiraiCodeMessage(string code)
+ {
+ Code = code;
+ }
+
+ ///
+ ///
+ ///
+ public MiraiCodeMessage()
+ {
+ }
+}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/MusicShareMessage.cs b/Mirai.Net/Data/Messages/Concretes/MusicShareMessage.cs
index 5d5df1f..01af217 100644
--- a/Mirai.Net/Data/Messages/Concretes/MusicShareMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/MusicShareMessage.cs
@@ -2,21 +2,48 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class MusicShareMessage : MessageBase
+///
+/// 音乐分享
+///
+public record MusicShareMessage : MessageBase
{
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.MusicShare;
+ ///
+ /// 类型,即分享自的软件平台
+ ///
[JsonProperty("kind")] public string Kind { get; set; }
+ ///
+ /// 标题
+ ///
[JsonProperty("title")] public string Title { get; set; }
+ ///
+ /// 概述
+ ///
[JsonProperty("summary")] public string Summary { get; set; }
+ ///
+ /// 跳转链接
+ ///
[JsonProperty("jumpUrl")] public string JumpUrl { get; set; }
+ ///
+ /// 封面链接
+ ///
[JsonProperty("pictureUrl")] public string PictureUrl { get; set; }
+ ///
+ /// 音乐链接
+ ///
[JsonProperty("musicUrl")] public string MusicUrl { get; set; }
+ ///
+ /// 简介
+ ///
[JsonProperty("brief")] public string Brief { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/PlainMessage.cs b/Mirai.Net/Data/Messages/Concretes/PlainMessage.cs
index afa328e..bd1cf6d 100644
--- a/Mirai.Net/Data/Messages/Concretes/PlainMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/PlainMessage.cs
@@ -2,18 +2,54 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class PlainMessage : MessageBase
+///
+/// 纯文本消息
+///
+public record PlainMessage : MessageBase
{
+ ///
+ /// 带参数的构造器
+ ///
+ ///
public PlainMessage(string text)
{
Text = text;
}
+ ///
+ ///
+ ///
public PlainMessage()
{
}
+ ///
+ /// 文本
+ ///
[JsonProperty("text")] public string Text { get; set; }
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.Plain;
+
+ ///
+ /// 可以和string相互转换
+ ///
+ ///
+ ///
+ public static implicit operator PlainMessage(string s)
+ {
+ return new PlainMessage(s);
+ }
+
+ ///
+ /// 可以和string相互转换
+ ///
+ ///
+ ///
+ public static implicit operator string(PlainMessage plainMessage)
+ {
+ return plainMessage.Text;
+ }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/PokeMessage.cs b/Mirai.Net/Data/Messages/Concretes/PokeMessage.cs
index 40ddedd..b6221d4 100644
--- a/Mirai.Net/Data/Messages/Concretes/PokeMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/PokeMessage.cs
@@ -2,7 +2,10 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class PokeMessage : MessageBase
+///
+/// 戳一戳系列消息
+///
+public record PokeMessage : MessageBase
{
///
/// "Poke": 戳一戳
@@ -15,5 +18,8 @@ public class PokeMessage : MessageBase
[JsonProperty("name")]
public string Name { get; set; }
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.Poke;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/QuoteMessage.cs b/Mirai.Net/Data/Messages/Concretes/QuoteMessage.cs
index be9c07d..468e251 100644
--- a/Mirai.Net/Data/Messages/Concretes/QuoteMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/QuoteMessage.cs
@@ -1,10 +1,16 @@
-using System.Collections.Generic;
-using Newtonsoft.Json;
+using Newtonsoft.Json;
+using System.Collections.Generic;
namespace Mirai.Net.Data.Messages.Concretes;
-public class QuoteMessage : MessageBase
+///
+/// 引用消息
+///
+public record QuoteMessage : MessageBase
{
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.Quote;
///
diff --git a/Mirai.Net/Data/Messages/Concretes/SourceMessage.cs b/Mirai.Net/Data/Messages/Concretes/SourceMessage.cs
index d00d110..424c705 100644
--- a/Mirai.Net/Data/Messages/Concretes/SourceMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/SourceMessage.cs
@@ -2,7 +2,11 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class SourceMessage : MessageBase
+///
+/// 源消息
+/// 仅在接收消息时有效,且总是消息链的第一个元素
+///
+public record SourceMessage : MessageBase
{
///
/// 消息id
@@ -16,5 +20,8 @@ public class SourceMessage : MessageBase
[JsonProperty("time")]
public string Time { get; set; }
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.Source;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/UnknownMessage.cs b/Mirai.Net/Data/Messages/Concretes/UnknownMessage.cs
new file mode 100644
index 0000000..06ad9fa
--- /dev/null
+++ b/Mirai.Net/Data/Messages/Concretes/UnknownMessage.cs
@@ -0,0 +1,36 @@
+using Newtonsoft.Json;
+
+namespace Mirai.Net.Data.Messages.Concretes;
+
+///
+/// 未知的(没有实现)的消息类型
+///
+public record UnknownMessage : MessageBase
+{
+ ///
+ ///
+ ///
+ [JsonIgnore] public override Messages Type { get; set; } = Messages.Unknown;
+
+ ///
+ /// 收到的json
+ ///
+ [JsonIgnore]
+ public string RawJson { get; set; }
+
+ ///
+ ///
+ ///
+ ///
+ public UnknownMessage(string rawJson)
+ {
+ RawJson = rawJson;
+ }
+
+ ///
+ ///
+ ///
+ public UnknownMessage()
+ {
+ }
+}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/VoiceMessage.cs b/Mirai.Net/Data/Messages/Concretes/VoiceMessage.cs
index a17d9cf..b8d5c54 100644
--- a/Mirai.Net/Data/Messages/Concretes/VoiceMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/VoiceMessage.cs
@@ -2,7 +2,10 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class VoiceMessage : MessageBase
+///
+/// 语音消息
+///
+public record VoiceMessage : MessageBase
{
///
/// 语音的voiceId,不为空时将忽略url属性
@@ -28,5 +31,8 @@ public class VoiceMessage : MessageBase
[JsonProperty("base64")]
public string Base64 { get; set; }
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.Voice;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Concretes/XmlMessage.cs b/Mirai.Net/Data/Messages/Concretes/XmlMessage.cs
index 20d7a82..277e57e 100644
--- a/Mirai.Net/Data/Messages/Concretes/XmlMessage.cs
+++ b/Mirai.Net/Data/Messages/Concretes/XmlMessage.cs
@@ -2,9 +2,18 @@
namespace Mirai.Net.Data.Messages.Concretes;
-public class XmlMessage : MessageBase
+///
+/// xml消息
+///
+public record XmlMessage : MessageBase
{
+ ///
+ /// 消息类型
+ ///
public override Messages Type { get; set; } = Messages.Xml;
+ ///
+ /// xml文本
+ ///
[JsonProperty("xml")] public string Xml { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/MessageBase.cs b/Mirai.Net/Data/Messages/MessageBase.cs
index 8faa661..55c91aa 100644
--- a/Mirai.Net/Data/Messages/MessageBase.cs
+++ b/Mirai.Net/Data/Messages/MessageBase.cs
@@ -1,11 +1,118 @@
-using Newtonsoft.Json;
+using Manganese.Text;
+using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
+using Mirai.Net.Data.Messages.Concretes;
namespace Mirai.Net.Data.Messages;
-public class MessageBase
+///
+/// 所有消息的基类
+///
+public record MessageBase
{
+ ///
+ /// 消息类型
+ ///
[JsonProperty("type")]
[JsonConverter(typeof(StringEnumConverter))]
public virtual Messages Type { get; set; }
+
+ ///
+ /// 实际上是转换成json文本
+ ///
+ ///
+ public override string ToString()
+ {
+ return this.ToJsonString();
+ }
+
+ ///
+ /// 提供Mirai码序列化方法
+ ///
+ ///
+ public string SerializeToMiraiCode()
+ {
+ switch (this)
+ {
+ case PlainMessage msg:
+
+ return msg.Text;
+
+ case FlashImageMessage msg:
+
+ return $"[mirai:flash:{msg.ImageId}]";
+
+ case ImageMessage msg:
+
+ if (string.IsNullOrEmpty(msg.ImageId))
+ throw new System.ArgumentNullException("ImageId为空!");
+
+ else
+ return $"[mirai:image:{msg.ImageId}]";
+
+ case AtMessage msg:
+
+ return $"[mirai:at:{msg.Target}]";
+
+ case AtAllMessage msg:
+
+ return "[mirai:atall]";
+
+ case FaceMessage msg:
+
+ if (string.IsNullOrEmpty(msg.FaceId))
+ throw new System.ArgumentNullException("FaceId为空!");
+
+ else
+ return $"[mirai:face:{msg.FaceId}]";
+
+ case PokeMessage msg:
+
+ var poke = msg.Name switch
+ {
+ "Poke" => "戳一戳,1,-1",
+
+ "ShowLove" => "比心,2,-1",
+
+ "Like" => "点赞,3,-1",
+
+ "Heartbroken" => "心碎,4,-1",
+
+ "SixSixSix" => "666,5,-1",
+
+ "FangDaZhao" => "放大招,6,-1",
+
+ _ => throw new System.NotSupportedException("该Poke消息还未支持!")
+ };
+
+ return $"[mirai:poke:{poke}]";
+
+ case DiceMessage msg:
+
+ return $"[mirai:dice:{msg.Value}]";
+
+ case MusicShareMessage msg: // MusicShare在mirai的2.15.0-M1版本中显示为[mirai:origin:MUSIC_SHARE]MusicShare(*这里有一长串省略的内容) 与https://github.com/mamoe/mirai/blob/dev/docs/Messages.md 中所说的[mirai:musicshare:$args]不符 因此这里先采用后者的方式 使用半角逗号分隔 至少保证序列化的稳定
+
+ return $"[mirai:musicshare:{msg.Kind},{msg.Title},{msg.Summary},{msg.JumpUrl},{msg.PictureUrl},{msg.MusicUrl},{msg.Brief}]";
+
+ case FileMessage msg: // FileMessage由于缺少参数(InternalId)目前是实验性功能 该参数自动使用Id补全
+
+ return $"[mirai:file:{msg.FileId},{msg.FileId},{msg.Name},{msg.Size}]";
+
+ default:
+
+ throw new System.NotSupportedException("遇到了不支持序列化的消息!");
+ }
+ }
+
+ ///
+ /// 自动转换成消息链
+ ///
+ ///
+ ///
+ ///
+ public static MessageChain operator +(MessageBase msg1, MessageBase msg2)
+ {
+ return new MessageChain { msg1, msg2 };
+ }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/MessageChain.cs b/Mirai.Net/Data/Messages/MessageChain.cs
new file mode 100644
index 0000000..a353ae3
--- /dev/null
+++ b/Mirai.Net/Data/Messages/MessageChain.cs
@@ -0,0 +1,7 @@
+namespace Mirai.Net.Data.Messages;
+
+//just a definition in Data namespace
+public partial class MessageChain
+{
+
+}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/MessageReceiverBase.cs b/Mirai.Net/Data/Messages/MessageReceiverBase.cs
index 9aec479..c872bba 100644
--- a/Mirai.Net/Data/Messages/MessageReceiverBase.cs
+++ b/Mirai.Net/Data/Messages/MessageReceiverBase.cs
@@ -1,14 +1,36 @@
-using System.Collections.Generic;
+using System.Threading.Tasks;
+using System;
+
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Mirai.Net.Data.Messages;
-public class MessageReceiverBase
+///
+/// 消息接收器基类
+///
+public record MessageReceiverBase
{
+ ///
+ /// 消息接收器类型
+ ///
[JsonProperty("type")]
[JsonConverter(typeof(StringEnumConverter))]
public virtual MessageReceivers Type { get; set; }
- [JsonProperty("messageChain")] public IEnumerable MessageChain { get; set; }
+ ///
+ /// 接受到的消息链
+ ///
+ [JsonProperty("messageChain")] public MessageChain MessageChain { get; set; }
+
+ ///
+ /// 发送消息
+ ///
+ /// 消息链
+ ///
+ /// 直接尝试呼叫此方法时掷出
+ public virtual Task SendMessageAsync(MessageChain chain)
+ {
+ throw new NotSupportedException("Direct call to virtual MessageReceiverBase.SendMessageAsync is not supported.");
+ }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/MessageReceivers.cs b/Mirai.Net/Data/Messages/MessageReceivers.cs
index 719b20f..104b967 100644
--- a/Mirai.Net/Data/Messages/MessageReceivers.cs
+++ b/Mirai.Net/Data/Messages/MessageReceivers.cs
@@ -3,20 +3,69 @@
namespace Mirai.Net.Data.Messages;
+///
+/// 消息接收器的类型
+///
public enum MessageReceivers
{
- [Description("FriendMessage")] [EnumMember(Value = "FriendMessage")]
+ ///
+ /// 好友消息
+ ///
+ [Description("FriendMessage")]
+ [EnumMember(Value = "FriendMessage")]
Friend,
- [Description("GroupMessage")] [EnumMember(Value = "GroupMessage")]
+ ///
+ /// 群消息
+ ///
+ [Description("GroupMessage")]
+ [EnumMember(Value = "GroupMessage")]
Group,
- [Description("TempMessage")] [EnumMember(Value = "TempMessage")]
+ ///
+ /// 临时消息
+ ///
+ [Description("TempMessage")]
+ [EnumMember(Value = "TempMessage")]
Temp,
- [Description("StrangerMessage")] [EnumMember(Value = "StrangerMessage")]
+ ///
+ /// 陌生人消息
+ ///
+ [Description("StrangerMessage")]
+ [EnumMember(Value = "StrangerMessage")]
Stranger,
- [Description("OtherClientMessage")] [EnumMember(Value = "OtherClientMessage")]
- OtherClient
+ ///
+ /// 其它客户端消息
+ ///
+ [Description("OtherClientMessage")]
+ [EnumMember(Value = "OtherClientMessage")]
+ OtherClient,
+
+ ///
+ /// 好友消息的同步消息
+ ///
+ [Description("FriendSyncMessage")]
+ [EnumMember(Value = "FriendSyncMessage")]
+ FriendSync,
+
+ ///
+ /// 群消息的同步消息
+ ///
+ [Description("GroupSyncMessage")]
+ [EnumMember(Value = "GroupSyncMessage")]
+ GroupSync,
+
+ ///
+ /// 临时消息的同步消息
+ ///
+ [Description("TempSyncMessage")]
+ [EnumMember(Value = "TempSyncMessage")]
+ TempSync,
+
+ ///
+ /// 未知类型的接收器
+ ///
+ Unknown
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Messages.cs b/Mirai.Net/Data/Messages/Messages.cs
index cbbf670..bfcaa26 100644
--- a/Mirai.Net/Data/Messages/Messages.cs
+++ b/Mirai.Net/Data/Messages/Messages.cs
@@ -1,22 +1,88 @@
namespace Mirai.Net.Data.Messages;
+///
+/// 消息类型
+///
public enum Messages
{
+ ///
+ /// 源消息
+ ///
Source,
+ ///
+ /// 引用消息
+ ///
Quote,
+ ///
+ /// @消息
+ ///
At,
+ ///
+ /// @全体成员消息
+ ///
AtAll,
+ ///
+ /// qq表情消息
+ ///
Face,
+ ///
+ /// 纯文本消息
+ ///
Plain,
+ ///
+ /// 图片消息
+ ///
Image,
+ ///
+ /// 闪照消息
+ ///
FlashImage,
+ ///
+ /// 语音消息
+ ///
Voice,
+ ///
+ /// xml消息
+ ///
Xml,
+ ///
+ /// json消息
+ ///
Json,
+ ///
+ /// app消息
+ ///
App,
+ ///
+ /// 不知道是啥玩意消息
+ ///
Poke,
+ ///
+ /// 骰子消息
+ ///
Dice,
+ ///
+ /// 音乐分享消息
+ ///
MusicShare,
+ ///
+ /// 转发消息
+ ///
Forward,
- File
+ ///
+ /// 文件消息
+ ///
+ File,
+ ///
+ /// 商城表情消息
+ ///
+ MarketFace,
+ ///
+ /// mirai码消息
+ ///
+ MiraiCode,
+ ///
+ /// 未知类型的消息
+ ///
+ Unknown
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Receivers/FriendMessageReceiver.cs b/Mirai.Net/Data/Messages/Receivers/FriendMessageReceiver.cs
index a8a7b46..88d196e 100644
--- a/Mirai.Net/Data/Messages/Receivers/FriendMessageReceiver.cs
+++ b/Mirai.Net/Data/Messages/Receivers/FriendMessageReceiver.cs
@@ -1,29 +1,59 @@
-using Mirai.Net.Data.Shared;
+using Mirai.Net.Data.Sessions;
+using System.Threading.Tasks;
+
+using Mirai.Net.Data.Shared;
+using Mirai.Net.Sessions.Http.Managers;
+
using Newtonsoft.Json;
namespace Mirai.Net.Data.Messages.Receivers;
-public class FriendMessageReceiver : MessageReceiverBase
+///
+/// 好友消息接收器
+///
+public record FriendMessageReceiver : MessageReceiverBase
{
+ ///
+ /// 消息接收器类型
+ ///
public override MessageReceivers Type { get; set; } = MessageReceivers.Friend;
+ ///
+ /// 发送者,某好友
+ ///
[JsonProperty("sender")] public Friend Sender { get; set; }
-
+
///
/// 好友昵称
///
[JsonIgnore]
- public string Name => Sender.NickName;
+ public string FriendName => Sender.NickName;
///
/// 好友备注
///
[JsonIgnore]
- public string Remark => Sender.Remark;
+ public string FriendRemark => Sender.Remark;
///
/// 好友QQ号
///
[JsonIgnore]
- public string Id => Sender.Id;
+ public string FriendId => Sender.Id;
+
+ ///
+ /// 发送好友消息
+ ///
+ /// 消息链
+ ///
+ public override async Task SendMessageAsync(MessageChain chain)
+ {
+ var payload = new
+ {
+ target = Sender.Id,
+ messageChain = chain
+ };
+
+ return await MessageManager.SendMessageAsync(HttpEndpoints.SendFriendMessage, payload);
+ }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Receivers/FriendSyncMessageReceiver.cs b/Mirai.Net/Data/Messages/Receivers/FriendSyncMessageReceiver.cs
new file mode 100644
index 0000000..7a7d254
--- /dev/null
+++ b/Mirai.Net/Data/Messages/Receivers/FriendSyncMessageReceiver.cs
@@ -0,0 +1,24 @@
+using Mirai.Net.Data.Shared;
+using Newtonsoft.Json;
+
+namespace Mirai.Net.Data.Messages.Receivers
+{
+
+ ///
+ /// 好友同步消息接收器
+ ///
+ public record FriendSyncMessageReceiver : MessageReceiverBase
+ {
+
+ ///
+ /// 消息接收器类型
+ ///
+ public override MessageReceivers Type { get; set; } = MessageReceivers.FriendSync;
+
+ ///
+ /// 好友信息
+ ///
+ [JsonProperty("subject")] public Friend TargetFriend { get; set; }
+
+ }
+}
diff --git a/Mirai.Net/Data/Messages/Receivers/GroupMessageReceiver.cs b/Mirai.Net/Data/Messages/Receivers/GroupMessageReceiver.cs
index c48f341..dfc4fc2 100644
--- a/Mirai.Net/Data/Messages/Receivers/GroupMessageReceiver.cs
+++ b/Mirai.Net/Data/Messages/Receivers/GroupMessageReceiver.cs
@@ -1,29 +1,59 @@
-using Mirai.Net.Data.Shared;
+using Mirai.Net.Data.Sessions;
+using System.Threading.Tasks;
+
+using Mirai.Net.Data.Shared;
+using Mirai.Net.Sessions.Http.Managers;
+
using Newtonsoft.Json;
namespace Mirai.Net.Data.Messages.Receivers;
-public class GroupMessageReceiver : MessageReceiverBase
+///
+/// 群消息接收器s
+///
+public record GroupMessageReceiver : MessageReceiverBase
{
+ ///
+ /// 消息接收器类型
+ ///
[JsonProperty("sender")] public Member Sender { get; set; }
///
/// 群号
///
[JsonIgnore]
- public string Id => Sender.Group.Id;
+ public string GroupId => Sender.Group.Id;
///
/// 群名称
///
[JsonIgnore]
- public string Name => Sender.Group.Name;
+ public string GroupName => Sender.Group.Name;
///
/// bot在群内的权限
///
[JsonIgnore]
- public Permissions Permission => Sender.Group.Permission;
+ public Permissions BotPermission => Sender.Group.Permission;
+ ///
+ /// 消息接收器类型
+ ///
public override MessageReceivers Type { get; set; } = MessageReceivers.Group;
+
+ ///
+ /// 发送群消息
+ ///
+ /// 消息链
+ ///
+ public override async Task SendMessageAsync(MessageChain chain)
+ {
+ var payload = new
+ {
+ target = Sender.Group.Id,
+ messageChain = chain
+ };
+
+ return await MessageManager.SendMessageAsync(HttpEndpoints.SendGroupMessage, payload);
+ }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Receivers/GroupSyncMessageReceiver.cs b/Mirai.Net/Data/Messages/Receivers/GroupSyncMessageReceiver.cs
new file mode 100644
index 0000000..0f64eeb
--- /dev/null
+++ b/Mirai.Net/Data/Messages/Receivers/GroupSyncMessageReceiver.cs
@@ -0,0 +1,24 @@
+using Mirai.Net.Data.Shared;
+using Newtonsoft.Json;
+
+namespace Mirai.Net.Data.Messages.Receivers
+{
+
+ ///
+ /// 群同步消息接收器
+ ///
+ public record GroupSyncMessageReceiver : MessageReceiverBase
+ {
+
+ ///
+ /// 消息接收器类型
+ ///
+ public override MessageReceivers Type { get; set; } = MessageReceivers.GroupSync;
+
+ ///
+ /// 群信息
+ ///
+ [JsonProperty("subject")] public Group TargetGroup { get; set; }
+
+ }
+}
diff --git a/Mirai.Net/Data/Messages/Receivers/OtherClientMessageReceiver.cs b/Mirai.Net/Data/Messages/Receivers/OtherClientMessageReceiver.cs
index aba4b4d..127ac4a 100644
--- a/Mirai.Net/Data/Messages/Receivers/OtherClientMessageReceiver.cs
+++ b/Mirai.Net/Data/Messages/Receivers/OtherClientMessageReceiver.cs
@@ -3,9 +3,18 @@
namespace Mirai.Net.Data.Messages.Receivers;
-public class OtherClientMessageReceiver : MessageReceiverBase
+///
+/// 其他客户端消息接收器
+///
+public record OtherClientMessageReceiver : MessageReceiverBase
{
+ ///
+ /// 消息接收器类型
+ ///
public override MessageReceivers Type { get; set; } = MessageReceivers.OtherClient;
+ ///
+ /// 发送者
+ ///
[JsonProperty("sender")] public OtherClient Sender { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Receivers/StrangerMessageReceiver.cs b/Mirai.Net/Data/Messages/Receivers/StrangerMessageReceiver.cs
index 7713d48..a02e154 100644
--- a/Mirai.Net/Data/Messages/Receivers/StrangerMessageReceiver.cs
+++ b/Mirai.Net/Data/Messages/Receivers/StrangerMessageReceiver.cs
@@ -3,27 +3,30 @@
namespace Mirai.Net.Data.Messages.Receivers;
-public class StrangerMessageReceiver : MessageReceiverBase
+///
+/// 陌生人接收器
+///
+public record StrangerMessageReceiver : MessageReceiverBase
{
+ ///
+ /// 消息接收器类型
+ ///
public override MessageReceivers Type { get; set; } = MessageReceivers.Stranger;
- [JsonProperty("sender")] public Friend Sender { get; set; }
-
///
- /// 昵称
+ /// 发送者
///
- [JsonIgnore]
- public string Name => Sender.NickName;
+ [JsonProperty("sender")] public Friend Sender { get; set; }
///
- /// 备注
+ /// 昵称
///
[JsonIgnore]
- public string Remark => Sender.Remark;
+ public string StrangerName => Sender.NickName;
///
/// QQ号
///
[JsonIgnore]
- public string Id => Sender.Id;
+ public string StrangerId => Sender.Id;
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Receivers/TempMessageReceiver.cs b/Mirai.Net/Data/Messages/Receivers/TempMessageReceiver.cs
index a7ff785..ad27e45 100644
--- a/Mirai.Net/Data/Messages/Receivers/TempMessageReceiver.cs
+++ b/Mirai.Net/Data/Messages/Receivers/TempMessageReceiver.cs
@@ -1,29 +1,59 @@
-using Mirai.Net.Data.Shared;
+using Mirai.Net.Data.Sessions;
+using System.Threading.Tasks;
+
+using Mirai.Net.Data.Shared;
+using Mirai.Net.Sessions.Http.Managers;
+
using Newtonsoft.Json;
namespace Mirai.Net.Data.Messages.Receivers;
-public class TempMessageReceiver : MessageReceiverBase
+///
+/// 临时消息接收器
+///
+public record TempMessageReceiver : MessageReceiverBase
{
+ ///
+ /// 消息接收器类型
+ ///
public override MessageReceivers Type { get; set; } = MessageReceivers.Temp;
+ ///
+ /// 发送者
+ ///
[JsonProperty("sender")] public Member Sender { get; set; }
-
+
///
/// 群号
///
[JsonIgnore]
- public string Id => Sender.Group.Id;
+ public string GroupId => Sender.Group.Id;
///
/// 群名称
///
[JsonIgnore]
- public string Name => Sender.Group.Name;
+ public string GroupName => Sender.Group.Name;
///
/// bot在群内的权限
///
[JsonIgnore]
- public Permissions Permission => Sender.Group.Permission;
+ public Permissions BotPermission => Sender.Group.Permission;
+
+ ///
+ /// 发送临时消息
+ ///
+ /// 消息链
+ ///
+ public override async Task SendMessageAsync(MessageChain chain)
+ {
+ var payload = new
+ {
+ target = Sender.Id,
+ messageChain = chain
+ };
+
+ return await MessageManager.SendMessageAsync(HttpEndpoints.SendTempMessage, payload);
+ }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Messages/Receivers/TempSyncMessageReceiver.cs b/Mirai.Net/Data/Messages/Receivers/TempSyncMessageReceiver.cs
new file mode 100644
index 0000000..50d480d
--- /dev/null
+++ b/Mirai.Net/Data/Messages/Receivers/TempSyncMessageReceiver.cs
@@ -0,0 +1,24 @@
+using Mirai.Net.Data.Shared;
+using Newtonsoft.Json;
+
+namespace Mirai.Net.Data.Messages.Receivers
+{
+
+ ///
+ /// 群临时消息同步消息接收器
+ ///
+ public record TempSyncMessageReceiver : MessageReceiverBase
+ {
+
+ ///
+ /// 消息接收器类型
+ ///
+ public override MessageReceivers Type { get; set; } = MessageReceivers.TempSync;
+
+ ///
+ /// 目标群成员的信息
+ ///
+ [JsonProperty("subject")] public Member TargetMember { get; set; }
+
+ }
+}
diff --git a/Mirai.Net/Data/Messages/Receivers/UnknownReceiver.cs b/Mirai.Net/Data/Messages/Receivers/UnknownReceiver.cs
new file mode 100644
index 0000000..7c7e681
--- /dev/null
+++ b/Mirai.Net/Data/Messages/Receivers/UnknownReceiver.cs
@@ -0,0 +1,37 @@
+using Newtonsoft.Json;
+
+namespace Mirai.Net.Data.Messages.Receivers;
+
+///
+/// 未知类型的消息接收器
+///
+public record UnknownReceiver : MessageReceiverBase
+{
+ ///
+ ///
+ ///
+ [JsonIgnore]
+ public override MessageReceivers Type { get; set; } = MessageReceivers.Unknown;
+
+ ///
+ /// 收到的json
+ ///
+ [JsonIgnore]
+ public string RawJson { get; set; }
+
+ ///
+ ///
+ ///
+ public UnknownReceiver()
+ {
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public UnknownReceiver(string rawJson)
+ {
+ RawJson = rawJson;
+ }
+}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Modules/CommandTriggerAttribute.cs b/Mirai.Net/Data/Modules/CommandTriggerAttribute.cs
deleted file mode 100644
index 5fdb5cc..0000000
--- a/Mirai.Net/Data/Modules/CommandTriggerAttribute.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System;
-
-namespace Mirai.Net.Data.Modules;
-
-///
-///
-/// /hello --arg1 value1 value2 --arg2 --arg3
-/// /: prefix
-/// hello : name
-/// -- : args separator
-///
-///
-[AttributeUsage(AttributeTargets.Method)]
-[Obsolete]
-public class CommandTriggerAttribute : Attribute
-{
- public CommandTriggerAttribute(string name, string prefix = "/", string argsSeparator = "-", bool equalName = false)
- {
- Prefix = prefix;
- Name = name;
- ArgsSeparator = argsSeparator;
- EqualName = equalName;
- }
-
- public string Prefix { get; set; }
-
- public string Name { get; set; }
-
- public string ArgsSeparator { get; set; }
-
- ///
- /// 命令中是否只能包含Name
- ///
- public bool EqualName { get; set; }
-}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Sessions/ConnectConfig.cs b/Mirai.Net/Data/Sessions/ConnectConfig.cs
new file mode 100644
index 0000000..1bff492
--- /dev/null
+++ b/Mirai.Net/Data/Sessions/ConnectConfig.cs
@@ -0,0 +1,104 @@
+using Manganese.Text;
+using Mirai.Net.Data.Exceptions;
+using System.Linq;
+
+namespace Mirai.Net.Data.Sessions
+{
+
+ ///
+ /// 连接配置
+ ///
+ public record ConnectConfig
+ {
+ ///
+ /// http连接配置
+ ///
+ public AdapterConfig HttpAddress { get; set; }
+
+ ///
+ /// websocket连接配置
+ ///
+ public AdapterConfig WebsocketAddress { get; set; }
+
+ ///
+ /// 从地址构造连接配置
+ ///
+ ///
+ ///
+ public static implicit operator ConnectConfig(string address)
+ {
+ return new ConnectConfig
+ {
+ HttpAddress = address,
+ WebsocketAddress = address
+ };
+ }
+
+ ///
+ /// 连接配置转换成地址
+ ///
+ ///
+ ///
+ ///
+ public static implicit operator string(ConnectConfig config)
+ {
+ if (config.HttpAddress != config.WebsocketAddress)
+ {
+ throw new InvalidAddressException("只有相同的地址才能转换为字符串");
+ }
+
+ return $"{config.HttpAddress.Host}:{config.HttpAddress.Port}";
+ }
+
+ ///
+ /// 适配器配置
+ ///
+ ///
+ ///
+ public record AdapterConfig(string Host, string Port)
+ {
+ ///
+ /// 从string自动转换成ip:port对
+ ///
+ ///
+ ///
+ public static implicit operator AdapterConfig(string address)
+ {
+ address = address.TrimEnd('/').Empty("http://").Empty("https://");
+ if (!address.Contains(':')) throw new InvalidAddressException($"错误的地址: {address}");
+
+ var split = address.Split(':');
+
+ if (split.Length != 2) throw new InvalidAddressException($"错误的地址: {address}");
+ if (!split.Last().IsInteger()) throw new InvalidAddressException($"错误的地址: {address}");
+
+ return new AdapterConfig(split[0], split[1]);
+ }
+
+ ///
+ /// 转换为string
+ ///
+ ///
+ ///
+ public static implicit operator string(AdapterConfig config)
+ {
+ return $"{config.Host}:{config.Port}";
+ }
+
+ ///
+ /// this
+ ///
+ ///
+ public override string ToString()
+ {
+ return this;
+ }
+ }
+ }
+}
+
+
+namespace System.Runtime.CompilerServices
+{
+ internal static class IsExternalInit { }
+}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Sessions/HttpEndpoints.cs b/Mirai.Net/Data/Sessions/HttpEndpoints.cs
index 6cd6420..19bd793 100644
--- a/Mirai.Net/Data/Sessions/HttpEndpoints.cs
+++ b/Mirai.Net/Data/Sessions/HttpEndpoints.cs
@@ -24,6 +24,7 @@ internal enum HttpEndpoints
[Description("sendTempMessage")] SendTempMessage,
[Description("sendNudge")] SendNudge,
[Description("recall")] Recall,
+ [Description("roamingMessages")] RoamingMessages,
[Description("file/list")] FileList,
[Description("file/info")] FileInfo,
@@ -47,6 +48,11 @@ internal enum HttpEndpoints
[Description("setEssence")] SetEssence,
[Description("groupConfig")] GroupConfig,
[Description("memberInfo")] MemberInfo,
+ [Description("userProfile")] UserProfile,
+
+ [Description("anno/list")] GetAnnouncement,
+ [Description("anno/publish")] PubAnnouncement,
+ [Description("anno/delete")] DelAnnouncement,
[Description("resp/newFriendRequestEvent")]
NewFriendRequested,
@@ -56,7 +62,10 @@ internal enum HttpEndpoints
[Description("resp/botInvitedJoinGroupRequestEvent")]
BotInvited,
-
+
[Description("messageFromId")]
- MessageFromId
+ MessageFromId,
+
+ [Description("cmd/execute")] ExecuteCommand,
+ [Description("cmd/register")] RegisterCommand
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Sessions/WebsocketEndpoints.cs b/Mirai.Net/Data/Sessions/WebsocketEndpoints.cs
deleted file mode 100644
index 913375e..0000000
--- a/Mirai.Net/Data/Sessions/WebsocketEndpoints.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.ComponentModel;
-
-namespace Mirai.Net.Data.Sessions;
-
-///
-/// MiraiBot类内部需要的Websocket请求端点
-///
-internal enum WebsocketEndpoints
-{
- [Description("message")] Message,
- [Description("all")] All,
- [Description("event")] Event
-}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Sessions/WebsocketMessageTypes.cs b/Mirai.Net/Data/Sessions/WebsocketMessageTypes.cs
deleted file mode 100644
index 834a506..0000000
--- a/Mirai.Net/Data/Sessions/WebsocketMessageTypes.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace Mirai.Net.Data.Sessions;
-
-internal enum WebsocketMessageTypes
-{
- Message,
- Event,
- Unknown
-}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Shared/Announcement.cs b/Mirai.Net/Data/Shared/Announcement.cs
new file mode 100644
index 0000000..783342d
--- /dev/null
+++ b/Mirai.Net/Data/Shared/Announcement.cs
@@ -0,0 +1,53 @@
+using Newtonsoft.Json;
+
+namespace Mirai.Net.Data.Shared
+{
+ ///
+ /// 群公告
+ ///
+ public record Announcement
+ {
+ ///
+ /// 群信息
+ ///
+ [JsonProperty("group")]
+ public Group Group { get; set; }
+
+ ///
+ /// 群公告内容
+ ///
+ [JsonProperty("content")]
+ public string Content { get; set; }
+
+ ///
+ /// 发布者账号
+ ///
+ [JsonProperty("senderID")]
+ public string SenderID { get; set; }
+
+ ///
+ /// 公告唯一id
+ ///
+ [JsonProperty("fid")]
+ public string Fid { get; set; }
+
+ ///
+ /// 是否所有群成员已确认
+ ///
+ [JsonProperty("allConfirmed")]
+ public bool AllConfirmed { get; set; }
+
+ ///
+ /// 确认群成员人数
+ ///
+ [JsonProperty("confirmedMembersCount")]
+ public string ConfirmedMembersCount { get; set; }
+
+ ///
+ /// 发布时间
+ ///
+ [JsonProperty("publicationTime")]
+ public string PublicationTime { get; set; }
+
+ }
+}
diff --git a/Mirai.Net/Data/Shared/AnnouncementSetting.cs b/Mirai.Net/Data/Shared/AnnouncementSetting.cs
new file mode 100644
index 0000000..b2ada0b
--- /dev/null
+++ b/Mirai.Net/Data/Shared/AnnouncementSetting.cs
@@ -0,0 +1,72 @@
+using Newtonsoft.Json;
+
+namespace Mirai.Net.Data.Shared
+{
+ ///
+ /// 群公告设置
+ ///
+ public record AnnouncementSetting
+ {
+
+ ///
+ /// 群号
+ ///
+ [JsonProperty("target")]
+ public string Target { get; set; }
+
+ ///
+ /// 公告内容
+ ///
+ [JsonProperty("content")]
+ public string Content { get; set; } = "";
+
+ ///
+ /// 是否发送给新成员
+ ///
+ [JsonProperty("sendToNewMember")]
+ public bool SendToNewMember { get; set; } = false;
+
+ ///
+ /// 是否置顶
+ ///
+ [JsonProperty("pinned")]
+ public bool Pinned { get; set; } = false;
+
+ ///
+ /// 是否显示群成员修改群名片的引导
+ ///
+ [JsonProperty("showEditCard")]
+ public bool ShowEditCard { get; set; } = false;
+
+ ///
+ /// 是否自动弹出
+ ///
+ [JsonProperty("showPopup")]
+ public bool ShowPopup { get; set; } = false;
+
+ ///
+ /// 是否需要群成员确认
+ ///
+ [JsonProperty("requireConfirmation")]
+ public bool RequireConfirmation { get; set; } = false;
+
+ ///
+ /// 公告图片url
+ ///
+ [JsonProperty("imageUrl")]
+ public string ImageUrl { get; set; }
+
+ ///
+ /// 公告图片本地路径
+ ///
+ [JsonProperty("imagePath")]
+ public string ImagePath { get; set; }
+
+ ///
+ /// 公告图片base64编码
+ ///
+ [JsonProperty("imageBase64")]
+ public string ImageBase64 { get; set; }
+
+ }
+}
diff --git a/Mirai.Net/Data/Shared/File.cs b/Mirai.Net/Data/Shared/File.cs
index cf662fd..be8e907 100644
--- a/Mirai.Net/Data/Shared/File.cs
+++ b/Mirai.Net/Data/Shared/File.cs
@@ -3,53 +3,116 @@
namespace Mirai.Net.Data.Shared;
-public class File
+///
+/// 文件
+///
+public record File
{
+ ///
+ /// 文件名
+ ///
[JsonProperty("name")] public string Name { get; set; }
+ ///
+ /// 文件标识id
+ ///
[JsonProperty("id")] public string Id { get; set; }
+ ///
+ /// 文件路径
+ ///
[JsonProperty("path")] public string Path { get; set; }
+ ///
+ /// 父目录
+ ///
[JsonProperty("parent")] public File Parent { get; set; }
+ ///
+ /// 是不是文件
+ ///
[JsonProperty("isFile")] public bool IsFile { get; set; }
+ ///
+ /// 是不是母鹿
+ ///
[JsonProperty("isDirectory")] public bool IsDirectory { get; set; }
+ ///
+ /// 上传者
+ ///
[JsonProperty("contact")] public FileUploader Contact { get; set; }
+ ///
+ /// 下载信息
+ ///
[JsonProperty("downloadInfo")] public FileDownloadInfo DownloadInfo { get; set; }
- public class FileUploader
+ ///
+ /// 文件上传者
+ ///
+ public record FileUploader
{
+ ///
+ /// 上传者qq
+ ///
[JsonProperty("id")] public string Id { get; set; }
+ ///
+ /// 上传者昵称
+ ///
[JsonProperty("name")] public string Name { get; set; }
+ ///
+ /// 上传者在群内的权限
+ ///
[JsonProperty("permission")]
[JsonConverter(typeof(StringEnumConverter))]
public Permissions Permission { get; set; }
}
- public class FileDownloadInfo
+ ///
+ /// 文件下载信息
+ ///
+ public record FileDownloadInfo
{
+ ///
+ /// sha1
+ ///
[JsonProperty("sha1")] public string Sha1 { get; set; }
+ ///
+ /// md5
+ ///
[JsonProperty("md5")] public string Md5 { get; set; }
+ ///
+ /// 下载链接
+ ///
[JsonProperty("url")] public string Url { get; set; }
-
+
+ ///
+ /// 下载次数
+ ///
[JsonProperty("downloadTimes")]
- public string DownloadTimes {get; set;}
-
+ public string DownloadTimes { get; set; }
+
+ ///
+ /// 上传者id
+ ///
[JsonProperty("uploaderId")]
- public string UploaderId {get; set;}
-
+ public string UploaderId { get; set; }
+
+ ///
+ /// 上传时间戳
+ ///
[JsonProperty("uploadTime")]
- public string UploadTime {get; set;}
-
+ public string UploadTime { get; set; }
+
+ ///
+ /// 最后修改时间
+ ///
[JsonProperty("lastModifyTime")]
- public string LastModifyTime {get; set;}
+ public string LastModifyTime { get; set; }
}
}
diff --git a/Mirai.Net/Data/Shared/Friend.cs b/Mirai.Net/Data/Shared/Friend.cs
index 40ad90a..76f5db1 100644
--- a/Mirai.Net/Data/Shared/Friend.cs
+++ b/Mirai.Net/Data/Shared/Friend.cs
@@ -3,9 +3,15 @@
namespace Mirai.Net.Data.Shared;
-public class Friend
+///
+/// 好友
+///
+public record Friend
{
- [JsonIgnore] public Profile Profile => this.GetFriendProfileAsync().GetAwaiter().GetResult();
+ ///
+ /// 好友的资料
+ ///
+ [JsonIgnore] public Profile FriendProfile => this.GetFriendProfileAsync().GetAwaiter().GetResult();
///
/// 好友的QQ号
diff --git a/Mirai.Net/Data/Shared/Genders.cs b/Mirai.Net/Data/Shared/Genders.cs
index af0f15e..b3398b2 100644
--- a/Mirai.Net/Data/Shared/Genders.cs
+++ b/Mirai.Net/Data/Shared/Genders.cs
@@ -3,14 +3,29 @@
namespace Mirai.Net.Data.Shared;
+///
+/// 发送者的性别
+///
public enum Genders
{
- [EnumMember(Value = "MALE")] [Description("MALE")]
+ ///
+ /// 男性
+ ///
+ [EnumMember(Value = "MALE")]
+ [Description("MALE")]
Male,
- [EnumMember(Value = "FEMALE")] [Description("FEMALE")]
+ ///
+ /// 女性
+ ///
+ [EnumMember(Value = "FEMALE")]
+ [Description("FEMALE")]
Female,
- [EnumMember(Value = "UNKNOWN")] [Description("UNKNOWN")]
+ ///
+ /// 未知
+ ///
+ [EnumMember(Value = "UNKNOWN")]
+ [Description("UNKNOWN")]
Unknown
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Shared/Group.cs b/Mirai.Net/Data/Shared/Group.cs
index b525b85..3ce9091 100644
--- a/Mirai.Net/Data/Shared/Group.cs
+++ b/Mirai.Net/Data/Shared/Group.cs
@@ -3,7 +3,10 @@
namespace Mirai.Net.Data.Shared;
-public class Group
+///
+/// 群
+///
+public record Group
{
///
/// 群号
diff --git a/Mirai.Net/Data/Shared/GroupSetting.cs b/Mirai.Net/Data/Shared/GroupSetting.cs
index 6671db1..01ae1d0 100644
--- a/Mirai.Net/Data/Shared/GroupSetting.cs
+++ b/Mirai.Net/Data/Shared/GroupSetting.cs
@@ -2,7 +2,10 @@
namespace Mirai.Net.Data.Shared;
-public class GroupSetting
+///
+/// 群设置
+///
+public record GroupSetting
{
///
/// 群名称
diff --git a/Mirai.Net/Data/Shared/ImageUploadTargets.cs b/Mirai.Net/Data/Shared/ImageUploadTargets.cs
index 7aa1bab..a44272b 100644
--- a/Mirai.Net/Data/Shared/ImageUploadTargets.cs
+++ b/Mirai.Net/Data/Shared/ImageUploadTargets.cs
@@ -3,14 +3,29 @@
namespace Mirai.Net.Data.Shared;
+///
+/// 图片上传目标
+///
public enum ImageUploadTargets
{
- [Description("friend")] [EnumMember(Value = "friend")]
+ ///
+ /// 好友
+ ///
+ [Description("friend")]
+ [EnumMember(Value = "friend")]
Friend,
- [Description("group")] [EnumMember(Value = "group")]
+ ///
+ /// 群
+ ///
+ [Description("group")]
+ [EnumMember(Value = "group")]
Group,
- [Description("temp")] [EnumMember(Value = "temp")]
+ ///
+ /// 临时消息
+ ///
+ [Description("temp")]
+ [EnumMember(Value = "temp")]
Temp
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Shared/Member.cs b/Mirai.Net/Data/Shared/Member.cs
index 12ed8f7..bcd2f09 100644
--- a/Mirai.Net/Data/Shared/Member.cs
+++ b/Mirai.Net/Data/Shared/Member.cs
@@ -7,10 +7,13 @@ namespace Mirai.Net.Data.Shared;
///
/// 群成员
///
-public class Member
+public record Member
{
- [JsonIgnore] public Profile Profile => this.GetMemberProfileAsync().GetAwaiter().GetResult();
-
+ ///
+ /// 群员资料
+ ///
+ [JsonIgnore] public Profile MemberProfile => this.GetMemberProfileAsync().GetAwaiter().GetResult();
+
///
/// 群员的QQ号
///
@@ -59,4 +62,4 @@ public class Member
///
[JsonProperty("group")]
public Group Group { get; set; }
-}
\ No newline at end of file
+}
diff --git a/Mirai.Net/Data/Shared/NewFriendRequestHandlers.cs b/Mirai.Net/Data/Shared/NewFriendRequestHandlers.cs
index 333b5ba..c420621 100644
--- a/Mirai.Net/Data/Shared/NewFriendRequestHandlers.cs
+++ b/Mirai.Net/Data/Shared/NewFriendRequestHandlers.cs
@@ -1,8 +1,20 @@
namespace Mirai.Net.Data.Shared;
+///
+/// 好友请求处理
+///
public enum NewFriendRequestHandlers
{
+ ///
+ /// 同意
+ ///
Approve = 0,
+ ///
+ /// 拒绝
+ ///
Reject = 1,
+ ///
+ /// 拒绝并屏蔽
+ ///
RejectAndBlock = 2
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Shared/NewInvitationRequestHandlers.cs b/Mirai.Net/Data/Shared/NewInvitationRequestHandlers.cs
index 0959301..7349593 100644
--- a/Mirai.Net/Data/Shared/NewInvitationRequestHandlers.cs
+++ b/Mirai.Net/Data/Shared/NewInvitationRequestHandlers.cs
@@ -1,7 +1,16 @@
namespace Mirai.Net.Data.Shared;
+///
+/// 新入群邀请处理
+///
public enum NewInvitationRequestHandlers
{
+ ///
+ /// 同意
+ ///
Approve,
+ ///
+ /// 拒绝
+ ///
Reject
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Shared/NewMemberRequestHandlers.cs b/Mirai.Net/Data/Shared/NewMemberRequestHandlers.cs
index d905352..f76975d 100644
--- a/Mirai.Net/Data/Shared/NewMemberRequestHandlers.cs
+++ b/Mirai.Net/Data/Shared/NewMemberRequestHandlers.cs
@@ -1,10 +1,28 @@
namespace Mirai.Net.Data.Shared;
+///
+/// 新成员进群处理
+///
public enum NewMemberRequestHandlers
{
+ ///
+ /// 同意
+ ///
Approve = 0,
+ ///
+ /// 拒绝
+ ///
Reject = 1,
+ ///
+ /// 忽略
+ ///
Dismiss = 2,
+ ///
+ /// 拒绝并拉黑
+ ///
RejectAndBlock = 3,
+ ///
+ /// 忽略
+ ///
DismissAndBlock = 4
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Shared/OtherClient.cs b/Mirai.Net/Data/Shared/OtherClient.cs
index 78537b4..46df0c9 100644
--- a/Mirai.Net/Data/Shared/OtherClient.cs
+++ b/Mirai.Net/Data/Shared/OtherClient.cs
@@ -2,9 +2,18 @@
namespace Mirai.Net.Data.Shared;
-public class OtherClient
+///
+/// 其它客户端
+///
+public record OtherClient
{
- [JsonProperty("id")] public string Id { get; set; }
+ ///
+ /// 客户端id
+ ///
+ [JsonProperty("id")] public int Id { get; set; }
+ ///
+ /// 平台
+ ///
[JsonProperty("platform")] public string Platform { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Shared/Permissions.cs b/Mirai.Net/Data/Shared/Permissions.cs
index 37facd0..392cb97 100644
--- a/Mirai.Net/Data/Shared/Permissions.cs
+++ b/Mirai.Net/Data/Shared/Permissions.cs
@@ -3,14 +3,29 @@
namespace Mirai.Net.Data.Shared;
+///
+/// 群内权限
+///
public enum Permissions
{
- [EnumMember(Value = "OWNER")] [Description("OWNER")]
+ ///
+ /// 群主
+ ///
+ [EnumMember(Value = "OWNER")]
+ [Description("OWNER")]
Owner,
- [EnumMember(Value = "ADMINISTRATOR")] [Description("ADMINISTRATOR")]
+ ///
+ /// 管理员
+ ///
+ [EnumMember(Value = "ADMINISTRATOR")]
+ [Description("ADMINISTRATOR")]
Administrator,
- [EnumMember(Value = "MEMBER")] [Description("MEMBER")]
+ ///
+ /// 群员
+ ///
+ [EnumMember(Value = "MEMBER")]
+ [Description("MEMBER")]
Member
}
\ No newline at end of file
diff --git a/Mirai.Net/Data/Shared/Profile.cs b/Mirai.Net/Data/Shared/Profile.cs
index 2f93df1..2ec4690 100644
--- a/Mirai.Net/Data/Shared/Profile.cs
+++ b/Mirai.Net/Data/Shared/Profile.cs
@@ -3,14 +3,29 @@
namespace Mirai.Net.Data.Shared;
-public class Profile
+///
+/// 资料卡
+///
+public record Profile
{
+ ///
+ /// 昵称
+ ///
[JsonProperty("nickname")] public string NickName { get; set; }
+ ///
+ /// 邮箱
+ ///
[JsonProperty("email")] public string Email { get; set; }
+ ///
+ /// 年龄
+ ///
[JsonProperty("age")] public string Age { get; set; }
+ ///
+ /// 等级
+ ///
[JsonProperty("level")] public string Level { get; set; }
///
@@ -19,6 +34,9 @@ public class Profile
[JsonProperty("sign")]
public string Signature { get; set; }
+ ///
+ /// 性别
+ ///
[JsonProperty("sex")]
[JsonConverter(typeof(StringEnumConverter))]
public Genders Gender { get; set; }
diff --git a/Mirai.Net/Mirai.Net.csproj b/Mirai.Net/Mirai.Net.csproj
index da04a1b..c65ee44 100644
--- a/Mirai.Net/Mirai.Net.csproj
+++ b/Mirai.Net/Mirai.Net.csproj
@@ -1,23 +1,33 @@
- netstandard2.0
latest
true
- 2.4.0-Pre1
+ 2.5.1
Mirai.Net
+ latest
基于mirai-api-http的轻量级mirai社区sdk
Copyright 2022 AHpx reserve all rights.
https://github.com/SinoAHpx/Mirai.Net
AGPL-3.0-only
https://github.com/SinoAHpx/Mirai.Net
+ Mirai, QQBot, mirai-api-http
+ netstandard2.0
+
+
+
+ bin\Debug\Mirai.Net.xml
+
+
+
+ bin\Release\Mirai.Net.xml
-
-
-
-
+
+
+
+
<_Parameter1>Mirai.Net.UnitTest
diff --git a/Mirai.Net/Modules/ICommandModule.cs b/Mirai.Net/Modules/ICommandModule.cs
deleted file mode 100644
index c001ad7..0000000
--- a/Mirai.Net/Modules/ICommandModule.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using Mirai.Net.Data.Messages;
-using Mirai.Net.Data.Modules;
-
-namespace Mirai.Net.Modules;
-
-[Obsolete("请使用IModule以体验全新的命令-模块系统")]
-public interface ICommandModule
-{
- public bool? IsEnable { get; set; }
-
- [CommandTrigger(nameof(ICommandModule))]
- public void Execute(MessageReceiverBase receiver, MessageBase executeMessage);
-}
\ No newline at end of file
diff --git a/Mirai.Net/Modules/IModule.cs b/Mirai.Net/Modules/IModule.cs
index 8713c56..eba7499 100644
--- a/Mirai.Net/Modules/IModule.cs
+++ b/Mirai.Net/Modules/IModule.cs
@@ -2,8 +2,19 @@
namespace Mirai.Net.Modules;
+///
+/// 模块化接口
+///
public interface IModule
{
+ ///
+ /// 执行器
+ ///
+ ///
void Execute(MessageReceiverBase @base);
+
+ ///
+ /// 是否启用模块
+ ///
bool? IsEnable { get; set; }
}
\ No newline at end of file
diff --git a/Mirai.Net/NuGet.config b/Mirai.Net/NuGet.config
new file mode 100644
index 0000000..2261421
--- /dev/null
+++ b/Mirai.Net/NuGet.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Mirai.Net/Sessions/Http/Managers/AccountManager.cs b/Mirai.Net/Sessions/Http/Managers/AccountManager.cs
index 6d41059..6888314 100644
--- a/Mirai.Net/Sessions/Http/Managers/AccountManager.cs
+++ b/Mirai.Net/Sessions/Http/Managers/AccountManager.cs
@@ -1,12 +1,11 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using AHpx.Extensions.JsonExtensions;
-using AHpx.Extensions.StringExtensions;
+using Manganese.Text;
using Mirai.Net.Data.Sessions;
using Mirai.Net.Data.Shared;
using Mirai.Net.Utils.Internal;
using Newtonsoft.Json;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
namespace Mirai.Net.Sessions.Http.Managers;
@@ -55,11 +54,11 @@ public static async Task> GetGroupsAsync()
///
/// 获取某群的全部群成员
///
- public static async Task> GetGroupMembersAsync(string target)
+ public static async Task> GetGroupMembersAsync(string groupId)
{
return await GetCollectionAsync(HttpEndpoints.MemberList, new
{
- target
+ target = groupId
});
}
@@ -74,12 +73,12 @@ public static async Task> GetGroupMembersAsync(this Group ta
///
/// 删除好友
///
- ///
- public static async Task DeleteFriendAsync(string target)
+ ///
+ public static async Task DeleteFriendAsync(string friendId)
{
_ = await HttpEndpoints.DeleteFriend.PostJsonAsync(new
{
- target
+ target = friendId
});
}
@@ -103,11 +102,11 @@ public static async Task GetBotProfileAsync()
///
/// 获取好友资料
///
- public static async Task GetFriendProfileAsync(string target)
+ public static async Task GetFriendProfileAsync(string friendId)
{
return await GetProfileAsync(HttpEndpoints.FriendProfile, new
{
- target
+ target = friendId
});
}
@@ -123,12 +122,12 @@ public static async Task GetFriendProfileAsync(this Friend target)
/// 获取群员资料
///
///
- /// 群号
- public static async Task GetMemberProfileAsync(string id, string target)
+ /// 群号
+ public static async Task GetMemberProfileAsync(string id, string memberId)
{
return await GetProfileAsync(HttpEndpoints.MemberProfile, new
{
- target,
+ target = memberId,
memberId = id
});
}
@@ -141,5 +140,16 @@ public static async Task GetMemberProfileAsync(this Member member)
return await GetMemberProfileAsync(member.Id, member.Group.Id);
}
+ ///
+ /// 获取任意QQ的资料(需要mirai-api-http 2.4.0及以上)
+ ///
+ public static async Task GetProfileAsync(string target)
+ {
+ return await GetProfileAsync(HttpEndpoints.UserProfile, new
+ {
+ target
+ });
+ }
+
#endregion
}
\ No newline at end of file
diff --git a/Mirai.Net/Sessions/Http/Managers/ConsoleManager.cs b/Mirai.Net/Sessions/Http/Managers/ConsoleManager.cs
new file mode 100644
index 0000000..e893309
--- /dev/null
+++ b/Mirai.Net/Sessions/Http/Managers/ConsoleManager.cs
@@ -0,0 +1,246 @@
+using Manganese.Array;
+using Mirai.Net.Data.Events;
+using Mirai.Net.Data.Messages;
+using Mirai.Net.Data.Messages.Concretes;
+using Mirai.Net.Data.Sessions;
+using Mirai.Net.Utils.Internal;
+using Newtonsoft.Json;
+using System.Collections.Generic;
+using System.Reactive;
+using System.Threading.Tasks;
+using System.Linq;
+
+namespace Mirai.Net.Sessions.Http.Managers
+{
+
+ ///
+ /// 控制台管理器
+ ///
+ public static class ConsoleManager
+ {
+#nullable enable
+ ///
+ /// 登录指令
+ /// 登录后的账号会生成新的SessionKey 使用已有的MiraiBot实例是无法连接到该账号的
+ /// 如果配置相同(QQ Address VerifyKey)可以再次在同一个MiraiBot上使用LaunchAsync方法之后就可以正常使用了
+ /// 在LaunchAsync之前使用的任何Subscribe方法都不会应用于新登录的账号 必须重新Subscribe
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task LoginAsync(string qq, string password, Protocol? protocol = null)
+ {
+ var command = protocol is null
+ ? new PlainMessage[] { $"/login {qq} {password}" }
+ : new PlainMessage[] { $"/login {qq} {password} {protocol.ToString()}" };
+
+ await HttpEndpoints.ExecuteCommand.PostJsonAsync(new
+ {
+ command
+ });
+ }
+#nullable restore
+
+ ///
+ /// 关闭指令
+ ///
+ ///
+ public static async Task StopAsync()
+ {
+ var command = new PlainMessage[] { "/stop" };
+
+ await HttpEndpoints.ExecuteCommand.PostJsonAsync(new
+ {
+ command
+ });
+ }
+
+ ///
+ /// 登出指令
+ ///
+ ///
+ ///
+ public static async Task LogoutAsync(string qq)
+ {
+ var command = new PlainMessage[] { $"/logout {qq}" };
+
+ await HttpEndpoints.ExecuteCommand.PostJsonAsync(new
+ {
+ command
+ });
+ }
+
+ ///
+ /// 执行命令
+ ///
+ ///
+ /// 命令与参数
+ ///
+ ///
+ public static async Task ExecuteCommandAsync(string commands)
+ {
+ var command = new PlainMessage[] { commands };
+
+ await HttpEndpoints.ExecuteCommand.PostJsonAsync(new
+ {
+ command
+ });
+ }
+
+ ///
+ /// 执行命令
+ ///
+ ///
+ /// 命令与参数
+ ///
+ ///
+ public static async Task ExecuteCommandAsync(params string[] commands)
+ {
+ var builder = new System.Text.StringBuilder();
+
+ foreach (var item in commands)
+ {
+ builder.Append(item);
+
+ builder.Append(' ');
+ }
+
+ var command = new PlainMessage[] { builder.ToString().Trim() };
+
+ await HttpEndpoints.ExecuteCommand.PostJsonAsync(new
+ {
+ command
+ });
+ }
+
+ ///
+ /// 使用消息执行命令
+ ///
+ ///
+ /// 命令与参数 如果使用纯文本的话需要将整条命令写在同一个PlainMessage中
+ /// 控制台支持以不同消息类型作为指令的参数, 执行命令需要以消息类型作为参数, 若执行纯文本的命令, 构建多个文本格式的消息控制台会将第一个消息作为指令名, 后续消息作为参数
+ ///
+ ///
+ public static async Task ExecuteMessageCommandAsync(IEnumerable command)
+ {
+ await HttpEndpoints.ExecuteCommand.PostJsonAsync(new
+ {
+ command
+ });
+ }
+
+ ///
+ /// 注册命令
+ /// 注册的命令会直接覆盖已有的指令(包括控制台内置的指令)
+ ///
+ /// 指令名
+ /// 使用说明
+ /// 命令描述
+ ///
+ public static async Task RegisterCommandAsync(string name, string usage, string description)
+ {
+ await HttpEndpoints.RegisterCommand.PostJsonAsync(new
+ {
+ name,
+ usage,
+ description
+ });
+ }
+
+ ///
+ /// 注册命令
+ /// 注册的命令会直接覆盖已有的指令(包括控制台内置的指令)
+ ///
+ /// 命令
+ ///
+ public static async Task RegisterCommandAsync(Command command)
+ {
+ await HttpEndpoints.RegisterCommand.PostJsonAsync(command);
+ }
+
+ ///
+ /// 注册用的命令
+ ///
+ public record Command
+ {
+
+ ///
+ /// 指令名
+ ///
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ ///
+ /// 指令别名
+ ///
+ [JsonProperty("alias")]
+ public IEnumerable Alias { get; set; }
+
+ ///
+ /// 使用说明
+ ///
+ [JsonProperty("usage")]
+ public string Usage { get; set; }
+
+ ///
+ /// 命令描述
+ ///
+ [JsonProperty("description")]
+ public string Description { get; set; }
+ }
+
+ ///
+ /// 命令被执行
+ ///
+ public record CommandExecutedEvent : EventBase
+ {
+ ///
+ /// 事件类型
+ ///
+ public override Events Type { get; set; } = Events.CommandExecuted;
+
+ ///
+ /// 命令名称
+ ///
+ [JsonProperty("name")] public string Name { get; set; }
+#nullable enable
+ ///
+ /// 发送命令的好友, 从控制台发送为 null
+ ///
+ [JsonProperty("friend")] public string? FriendId { get; set; }
+
+ ///
+ /// 发送命令的群成员, 从控制台发送为 null
+ ///
+ [JsonProperty("member")] public string? MemberId { get; set; }
+#nullable restore
+ ///
+ /// 指令的参数, 以消息类型传递
+ ///
+ [JsonProperty("args")] public dynamic Args { get; set; }
+ }
+
+ }
+
+ ///
+ /// 可选的登录协议
+ ///
+ public enum Protocol
+ {
+ ///
+ /// 安卓手机
+ ///
+ ANDROID_PHONE,
+
+ ///
+ /// 安卓平板
+ ///
+ ANDROID_PAD,
+
+ ///
+ /// 安卓手表
+ ///
+ ANDROID_WATCH
+ }
+}
diff --git a/Mirai.Net/Sessions/Http/Managers/FileManager.cs b/Mirai.Net/Sessions/Http/Managers/FileManager.cs
index 77ea187..5818035 100644
--- a/Mirai.Net/Sessions/Http/Managers/FileManager.cs
+++ b/Mirai.Net/Sessions/Http/Managers/FileManager.cs
@@ -1,32 +1,36 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using AHpx.Extensions.JsonExtensions;
-using AHpx.Extensions.StringExtensions;
-using Flurl.Http;
+using Flurl.Http;
+using Manganese.Text;
using Mirai.Net.Data.Sessions;
using Mirai.Net.Data.Shared;
using Mirai.Net.Utils.Internal;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+using File = Mirai.Net.Data.Shared.File;
namespace Mirai.Net.Sessions.Http.Managers;
+///
+/// 文件管理器
+///
public static class FileManager
{
///
/// 获取群文件列表
///
- ///
+ ///
/// 附带下载信息,默认不附带
/// 文件夹id,空字符串即为根目录
///
- [Obsolete("此方法因为mirai-api-http的缺陷,存在严重性能问题(只能获取少量群文件)。")]
- public static async Task> GetFilesAsync(string target, bool? withDownloadInfo = null,
+ public static async Task> GetFilesAsync(string groupId, bool? withDownloadInfo = null,
string folderId = "")
{
var result = await HttpEndpoints.FileList.GetAsync(new
{
- target,
+ target = groupId,
withDownloadInfo,
id = folderId
});
@@ -39,15 +43,15 @@ public static async Task> GetFilesAsync(string target, bool? w
///
/// 获取群文件信息
///
- /// 群号
+ /// 群号
/// 文件id
///
///
- public static async Task GetFileAsync(string target, string fileId, bool? withDownloadInfo = null)
+ public static async Task GetFileAsync(string groupId, string fileId, bool? withDownloadInfo = null)
{
var result = await HttpEndpoints.FileInfo.GetAsync(new
{
- target,
+ target = groupId,
id = fileId,
withDownloadInfo
});
@@ -58,15 +62,15 @@ public static async Task GetFileAsync(string target, string fileId, bool?
///
/// 创建群文件夹
///
- ///
+ ///
///
///
- public static async Task CreateFolderAsync(string target, string name)
+ public static async Task CreateFolderAsync(string groupId, string name)
{
var result = await HttpEndpoints.FileCreate.PostJsonAsync(new
{
id = "",
- target,
+ target = groupId,
directoryName = name
});
@@ -76,13 +80,13 @@ public static async Task CreateFolderAsync(string target, string name)
///
/// 删除群文件
///
- ///
+ ///
///
- public static async Task DeleteFileAsync(string target, string fileId)
+ public static async Task DeleteFileAsync(string groupId, string fileId)
{
_ = await HttpEndpoints.FileDelete.PostJsonAsync(new
{
- target,
+ target = groupId,
id = fileId
});
}
@@ -90,14 +94,14 @@ public static async Task DeleteFileAsync(string target, string fileId)
///
/// 移动群文件
///
- ///
+ ///
/// 移动文件id
/// 移动目标文件夹id
- public static async Task MoveFileAsync(string target, string fileId, string destination)
+ public static async Task MoveFileAsync(string groupId, string fileId, string destination)
{
_ = await HttpEndpoints.FileMove.PostJsonAsync(new
{
- target,
+ target = groupId,
id = fileId,
movoTo = destination
});
@@ -106,41 +110,53 @@ public static async Task MoveFileAsync(string target, string fileId, string dest
///
/// 重命名群文件
///
- ///
+ ///
/// 重命名文件id
/// 新文件名
- public static async Task RenameFileAsync(string target, string fileId, string newName)
+ public static async Task RenameFileAsync(string groupId, string fileId, string newName)
{
_ = await HttpEndpoints.FileRename.PostJsonAsync(new
{
- target,
+ target = groupId,
id = fileId,
renameTo = newName
});
}
///
- /// 上传群文件,参考https://github.com/project-mirai/mirai-api-http/issues/456
+ /// 上传群文件,修复 https://github.com/SinoAHpx/Mirai.Net/issues/72 中提到的编码错误
///
- /// 上传到哪个群
+ /// 上传到哪个群
/// 文件的路径
- /// 上传路径,例如/xx(不可以指定文件名,默认为上传到根目录)
+ /// 上传路径,例如/xx
+ /// 上传的文件名
/// 有几率返回null,这是个mirai-api-http的玄学问题
- public static async Task UploadFileAsync(string target, string filePath, string uploadPath = "/")
+ public static async Task UploadFileAsync(string groupId, string filePath, string uploadPath = "/", string fileName = null)
{
- uploadPath ??= $"/{filePath.FetchFileName()}";
+ fileName ??= Path.GetFileName(filePath);
- var url = $"http://{MiraiBot.Instance.Address}/{HttpEndpoints.FileUpload.GetDescription()}";
+ var url = $"http://{MiraiBot.Instance.Address.HttpAddress}/{HttpEndpoints.FileUpload.GetDescription()}";
- var result = await url
- .WithHeader("Authorization", $"session {MiraiBot.Instance.HttpSessionKey}")
- .PostMultipartAsync(x => x
- .AddString("type", "group")
- .AddString("path", uploadPath)
- .AddString("target", target)
- .AddFile("file", filePath));
+ using var fileStream = System.IO.File.Open(filePath, FileMode.Open);
+ var streamContent = new StreamContent(fileStream);
+ var hackedFileName = new string(Encoding.UTF8.GetBytes(fileName).Select(b => (char)b).ToArray());
+ streamContent.Headers.Add("Content-Disposition", $@"form-data; name=""file""; filename=""{hackedFileName}""; filename*=""{hackedFileName}""");
+
+ var response = await url
+ .PostAsync(new MultipartFormDataContent
+ {
+ { new StringContent(MiraiBot.Instance.HttpSessionKey), "sessionKey" },
+ { new StringContent("group"), "type" },
+ { new StringContent(groupId), "target" },
+ { new StringContent(uploadPath), "path" },
+ { streamContent, "file", fileName }
+ })
+ .ReceiveString();
+
+
+ response.EnsureSuccess("这大抵是个玄学问题罢。");
- var re = (await result.GetStringAsync()).ToJObject();
+ var re = response.ToJObject();
return !re.ContainsKey("name") ? null : re.ToObject();
}
@@ -154,7 +170,7 @@ public static async Task UploadFileAsync(string target, string filePath, s
public static async Task<(string, string)> UploadImageAsync(string imagePath,
ImageUploadTargets imageUploadTargets = ImageUploadTargets.Group)
{
- var url = $"http://{MiraiBot.Instance.Address}/{HttpEndpoints.UploadImage.GetDescription()}";
+ var url = $"http://{MiraiBot.Instance.Address.HttpAddress}/{HttpEndpoints.UploadImage.GetDescription()}";
var result = await url
.WithHeader("Authorization", $"session {MiraiBot.Instance.HttpSessionKey}")
@@ -163,6 +179,7 @@ public static async Task UploadFileAsync(string target, string filePath, s
.AddFile("img", imagePath));
var re = await result.GetStringAsync();
+ re.EnsureSuccess("这大抵是个玄学问题罢。");
return (re.Fetch("imageId"), re.Fetch("url"));
}
@@ -174,7 +191,7 @@ public static async Task UploadFileAsync(string target, string filePath, s
/// item1: 语音id,item2:语音url
public static async Task<(string, string)> UploadVoiceAsync(string voicePath)
{
- var url = $"http://{MiraiBot.Instance.Address}/{HttpEndpoints.UploadVoice.GetDescription()}";
+ var url = $"http://{MiraiBot.Instance.Address.HttpAddress}/{HttpEndpoints.UploadVoice.GetDescription()}";
var result = await url
.WithHeader("Authorization", $"session {MiraiBot.Instance.HttpSessionKey}")
@@ -183,6 +200,7 @@ public static async Task UploadFileAsync(string target, string filePath, s
.AddFile("voice", voicePath));
var re = await result.GetStringAsync();
+ re.EnsureSuccess("这大抵是个玄学问题罢。");
return (re.Fetch("voiceId"), re.Fetch("url"));
}
diff --git a/Mirai.Net/Sessions/Http/Managers/GroupManager.cs b/Mirai.Net/Sessions/Http/Managers/GroupManager.cs
index c0e926e..f7a8970 100644
--- a/Mirai.Net/Sessions/Http/Managers/GroupManager.cs
+++ b/Mirai.Net/Sessions/Http/Managers/GroupManager.cs
@@ -1,15 +1,21 @@
-using System;
-using System.Linq;
-using System.Threading.Tasks;
+using Manganese.Text;
using Mirai.Net.Data.Messages;
using Mirai.Net.Data.Messages.Concretes;
+using Mirai.Net.Data.Messages.Receivers;
using Mirai.Net.Data.Sessions;
using Mirai.Net.Data.Shared;
using Mirai.Net.Utils.Internal;
using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
namespace Mirai.Net.Sessions.Http.Managers;
+///
+/// 群管理器
+///
public static class GroupManager
{
#region Mute
@@ -17,15 +23,15 @@ public static class GroupManager
///
/// 禁言某群员
///
- ///
- ///
- ///
- public static async Task MuteAsync(string target, string group, int time)
+ /// 禁言对象的QQ号
+ /// 禁言对象所在的群号
+ /// 禁言的时长
+ public static async Task MuteAsync(string memberId, string group, int time)
{
var payload = new
{
target = group,
- memberId = target,
+ memberId = memberId,
time
};
@@ -33,16 +39,16 @@ public static async Task MuteAsync(string target, string group, int time)
}
///
- public static async Task MuteAsync(string target, string group, TimeSpan time)
+ public static async Task MuteAsync(string memberId, string group, TimeSpan time)
{
- await MuteAsync(target, group, Convert.ToInt32(time.TotalSeconds));
+ await MuteAsync(memberId, group, Convert.ToInt32(time.TotalSeconds));
}
///
/// 禁言某群员
///
- ///
- ///
+ /// 禁言的对象
+ /// 禁言的时长
public static async Task MuteAsync(this Member member, int time)
{
await MuteAsync(member.Id, member.Group.Id, time);
@@ -61,14 +67,14 @@ public static async Task MuteAsync(this Member member, TimeSpan time)
///
/// 取消禁言
///
- ///
- ///
- public static async Task UnMuteAsync(string target, string group)
+ /// 取消禁言对象的QQ号
+ /// 取消禁言对象所在的群号
+ public static async Task UnMuteAsync(string memberId, string group)
{
var payload = new
{
target = group,
- memberId = target
+ memberId
};
await HttpEndpoints.Unmute.PostJsonAsync(payload);
@@ -77,7 +83,7 @@ public static async Task UnMuteAsync(string target, string group)
///
/// 取消禁言
///
- ///
+ /// 取消禁言的对象
public static async Task UnMuteAsync(this Member member)
{
await UnMuteAsync(member.Id, member.Group.Id);
@@ -90,15 +96,15 @@ public static async Task UnMuteAsync(this Member member)
///
/// 踢出某群员
///
- ///
- ///
- ///
- public static async Task KickAsync(string target, string group, string message = "")
+ /// 踢出对象的QQ号
+ /// 踢出对象所在的群号
+ /// 踢出的原因
+ public static async Task KickAsync(string memberId, string group, string message = "")
{
var payload = new
{
target = group,
- memberId = target,
+ memberId = memberId,
msg = message
};
@@ -108,8 +114,8 @@ public static async Task KickAsync(string target, string group, string message =
///
/// 踢出某群员
///
- ///
- ///
+ /// 踢出的对象
+ /// 踢出的原因
public static async Task KickAsync(this Member member, string message = "")
{
await KickAsync(member.Id, member.Group.Id);
@@ -122,12 +128,12 @@ public static async Task KickAsync(this Member member, string message = "")
///
/// bot退出某群
///
- ///
- public static async Task LeaveAsync(string target)
+ /// 要退出的群号
+ public static async Task LeaveAsync(string groupId)
{
var payload = new
{
- target
+ groupId
};
await HttpEndpoints.Leave.PostJsonAsync(payload);
@@ -136,7 +142,7 @@ public static async Task LeaveAsync(string target)
///
/// bot退出某群
///
- ///
+ /// 要退出的群
public static async Task LeaveAsync(this Group group)
{
await LeaveAsync(group.Id);
@@ -149,14 +155,14 @@ public static async Task LeaveAsync(this Group group)
///
/// 全体禁言
///
- ///
- /// 是否禁言
- public static async Task MuteAllAsync(string target, bool mute = true)
+ /// 目标群号
+ /// 是否禁言。 false为解除禁言,true为禁言
+ public static async Task MuteAllAsync(string groupId, bool mute = true)
{
var endpoint = mute ? HttpEndpoints.MuteAll : HttpEndpoints.UnmuteAll;
var payload = new
{
- target
+ groupId
};
await endpoint.PostJsonAsync(payload);
@@ -165,8 +171,8 @@ public static async Task MuteAllAsync(string target, bool mute = true)
///
/// 全体禁言
///
- ///
- /// 是否禁言
+ /// 目标群
+ /// 是否禁言。 false为解除禁言,true为禁言
public static async Task MuteAllAsync(this Group group, bool mute = true)
{
await MuteAllAsync(group.Id, mute);
@@ -180,11 +186,13 @@ public static async Task MuteAllAsync(this Group group, bool mute = true)
/// 设置精华消息
///
/// 消息id
- public static async Task SetEssenceMessageAsync(string messageId)
+ /// 目标群号
+ public static async Task SetEssenceMessageAsync(string messageId, string groupId)
{
var payload = new
{
- target = messageId
+ target = groupId,
+ messageId
};
await HttpEndpoints.SetEssence.PostJsonAsync(payload);
@@ -196,12 +204,11 @@ public static async Task SetEssenceMessageAsync(string messageId)
///
public static async Task SetEssenceMessageAsync(this MessageReceiverBase receiver)
{
- var payload = new
+ if (receiver is GroupMessageReceiver groupMessageReceiver)
{
- target = receiver.MessageChain.OfType().First().MessageId
- };
-
- await HttpEndpoints.SetEssence.PostJsonAsync(payload);
+ await SetEssenceMessageAsync(receiver.MessageChain.OfType().Single().MessageId,
+ groupMessageReceiver.GroupId);
+ }
}
#endregion
@@ -211,11 +218,11 @@ public static async Task SetEssenceMessageAsync(this MessageReceiverBase receive
///
/// 获取群设置
///
- ///
+ /// 目标群号
///
- public static async Task GetGroupSettingAsync(string target)
+ public static async Task GetGroupSettingAsync(string groupId)
{
- var response = await HttpEndpoints.GroupConfig.GetAsync(new { target });
+ var response = await HttpEndpoints.GroupConfig.GetAsync(new { target = groupId });
return JsonConvert.DeserializeObject(response);
}
@@ -234,13 +241,13 @@ public static async Task GetGroupSettingAsync(this Group group)
///
/// 修改群设置
///
- ///
- ///
- public static async Task SetGroupSettingAsync(string target, GroupSetting setting)
+ /// 目标群号
+ /// 群设置
+ public static async Task SetGroupSettingAsync(string groupId, GroupSetting setting)
{
var payload = new
{
- target,
+ target = groupId,
config = setting
};
@@ -250,8 +257,8 @@ public static async Task SetGroupSettingAsync(string target, GroupSetting settin
///
/// 修改群设置
///
- ///
- ///
+ /// 目标群
+ /// 群设置
public static async Task SetGroupSettingAsync(this Group group, GroupSetting setting)
{
await SetGroupSettingAsync(group.Id, setting);
@@ -264,8 +271,8 @@ public static async Task SetGroupSettingAsync(this Group group, GroupSetting set
///
/// 获取群员
///
- ///
- ///
+ /// 目标的QQ号
+ /// 目标群号
///
public static async Task GetMemberAsync(string memberQQ, string group)
{
@@ -281,8 +288,8 @@ public static async Task GetMemberAsync(string memberQQ, string group)
///
/// 修改群员设置,需要相关的权限
///
- ///
- ///
+ /// 目标的QQ号
+ /// 目标群号
/// 群名片, 需要管理员权限
/// 群头衔, 需要群主权限
///
@@ -306,4 +313,74 @@ public static async Task SetMemberInfoAsync(string memberQQ, string grou
}
#endregion
+
+ #region Anno
+
+ ///
+ /// 获取指定群公告列表
+ ///
+ /// 目标群号
+ /// 分页参数
+ /// 分页参数,默认10
+ ///
+ public static async Task> GetGroupAnnouncementAsync(string group, long offset = 0, long size = 10)
+ {
+ var response = await HttpEndpoints.GetAnnouncement.GetAsync(new
+ {
+ id = group,
+ offset,
+ size
+ });
+
+ return JsonConvert.DeserializeObject>(response.Fetch("data"));
+ }
+
+ ///
+ /// 向指定群发布群公告
+ ///
+ /// 目标群号
+ /// 公告内容
+ /// 是否置顶
+ ///
+ public static async Task PublishGroupAnnouncementAsync(string group, string content, bool pinned = true)
+ {
+ var setting = new AnnouncementSetting
+ {
+ Target = group,
+ Content = content,
+ Pinned = pinned
+ };
+
+ return await PublishGroupAnnouncementAsync(setting);
+ }
+
+ ///
+ /// 向指定群发布群公告
+ ///
+ /// 群公告设置
+ ///
+ public static async Task PublishGroupAnnouncementAsync(AnnouncementSetting announcementSetting)
+ {
+ var response = await HttpEndpoints.PubAnnouncement.PostJsonAsync(announcementSetting);
+
+ return JsonConvert.DeserializeObject(response.Fetch("data"));
+ }
+
+ ///
+ /// 删除指定群中一条公告
+ ///
+ /// 目标群号
+ /// 群公告唯一id
+ ///
+ public static async Task DeleteGroupAnnouncementAsync(string group, string fid)
+ {
+ await HttpEndpoints.DelAnnouncement.PostJsonAsync(new
+ {
+ id = group,
+ fid
+ });
+ }
+
+ #endregion
+
}
\ No newline at end of file
diff --git a/Mirai.Net/Sessions/Http/Managers/MessageManager.cs b/Mirai.Net/Sessions/Http/Managers/MessageManager.cs
index 763e9e9..3b96e8f 100644
--- a/Mirai.Net/Sessions/Http/Managers/MessageManager.cs
+++ b/Mirai.Net/Sessions/Http/Managers/MessageManager.cs
@@ -1,19 +1,25 @@
-using System.Threading.Tasks;
-using AHpx.Extensions.JsonExtensions;
+using Manganese.Text;
+
using Mirai.Net.Data.Messages;
using Mirai.Net.Data.Sessions;
using Mirai.Net.Data.Shared;
-using Mirai.Net.Utils.Internal;
-using Mirai.Net.Utils.Scaffolds;
-using Newtonsoft.Json;
+using Mirai.Net.Utils.Internal;
+
+using Newtonsoft.Json;
+
+using System.Collections.Generic;
+using System.Threading.Tasks;
namespace Mirai.Net.Sessions.Http.Managers;
+///
+/// 消息管理器
+///
public static class MessageManager
{
- #region Private helpers
+ #region Non-Public helpers
- private static async Task SendMessageAsync(HttpEndpoints endpoints, object payload)
+ internal static async Task SendMessageAsync(HttpEndpoints endpoints, object payload)
{
var response = await endpoints.PostJsonAsync(payload);
@@ -27,29 +33,54 @@ private static async Task SendMessageAsync(HttpEndpoints endpoints, obje
///
/// 由消息id获取一条消息
///
+ /// 消息id
+ /// 好友id或群id
///
///
- public static async Task GetMessageReceiverByIdAsync(string messageId) where T : MessageReceiverBase
+ public static async Task GetMessageReceiverByIdAsync(string messageId, string target) where T : MessageReceiverBase
{
var response = await HttpEndpoints.MessageFromId.GetAsync(new
{
- id = messageId
+ messageId,
+ target
});
- return JsonConvert.DeserializeObject(response);
+ var data = response.Fetch("data")!;
+ var receiver = JsonConvert.DeserializeObject(data)!;
+ receiver.MessageChain = data.Fetch("messageChain").DeserializeMessageChain();
+
+ return receiver;
}
-
+
+ ///
+ /// 获取漫游消息(目前仅支持好友)
+ ///
+ /// 好友id或群id
+ /// 起始时间, UTC+8 时间戳, 单位为秒. 可以为 0, 即表示从可以获取的最早的消息起. 负数将会被看是 0.
+ /// 结束时间, UTC+8 时间戳, 单位为秒. 可以为 long.MaxValue, 即表示到可以获取的最晚的消息为止. 低于 timeStart 的值将会被看作是 timeStart 的值.
+ ///
+ public static async Task> GetRoamingMessagesAsync(string target, long timeStart = 0, long timeEnd = 0)
+ {
+ var response = await HttpEndpoints.RoamingMessages.PostJsonAsync(new
+ {
+ timeStart,
+ timeEnd,
+ target = target.ToInt64(),
+ });
+ return JsonConvert.DeserializeObject>(response.Fetch("data"));
+ }
+
///
/// 发送好友消息
///
- ///
+ ///
///
///
- public static async Task SendFriendMessageAsync(string target, params MessageBase[] chain)
+ public static async Task SendFriendMessageAsync(string friendId, MessageChain chain)
{
var payload = new
{
- target,
+ target = friendId,
messageChain = chain
};
@@ -62,7 +93,7 @@ public static async Task SendFriendMessageAsync(string target, params Me
///
///
///
- public static async Task SendFriendMessageAsync(this Friend friend, params MessageBase[] chain)
+ public static async Task SendFriendMessageAsync(this Friend friend, MessageChain chain)
{
return await SendFriendMessageAsync(friend.Id, chain);
}
@@ -70,14 +101,14 @@ public static async Task SendFriendMessageAsync(this Friend friend, para
///
/// 发送群消息
///
- ///
+ ///
///
///
- public static async Task SendGroupMessageAsync(string target, params MessageBase[] chain)
+ public static async Task SendGroupMessageAsync(string groupId, MessageChain chain)
{
var payload = new
{
- target,
+ target = groupId,
messageChain = chain
};
@@ -90,7 +121,7 @@ public static async Task SendGroupMessageAsync(string target, params Mes
///
///
///
- public static async Task SendGroupMessageAsync(this Group group, params MessageBase[] chain)
+ public static async Task SendGroupMessageAsync(this Group group, MessageChain chain)
{
return await SendGroupMessageAsync(group.Id, chain);
}
@@ -102,7 +133,7 @@ public static async Task SendGroupMessageAsync(this Group group, params
///
///
///
- public static async Task SendTempMessageAsync(string qq, string group, params MessageBase[] chain)
+ public static async Task SendTempMessageAsync(string qq, string group, MessageChain chain)
{
var payload = new
{
@@ -120,7 +151,7 @@ public static async Task SendTempMessageAsync(string qq, string group, p
///
///
///
- public static async Task SendTempMessageAsync(this Member member, params MessageBase[] chain)
+ public static async Task SendTempMessageAsync(this Member member, MessageChain chain)
{
return await SendTempMessageAsync(member.Id, member.Group.Id, chain);
}
@@ -147,11 +178,13 @@ public static async Task SendNudgeAsync(string target, string subject, MessageRe
/// 撤回消息
///
/// 消息id
- public static async Task RecallAsync(string messageId)
+ /// 好友id或群id
+ public static async Task RecallAsync(string messageId, string target)
{
var payload = new
{
- target = messageId
+ target,
+ messageId
};
await HttpEndpoints.Recall.PostJsonAsync(payload);
@@ -165,7 +198,7 @@ public static async Task RecallAsync(string messageId)
///
///
public static async Task QuoteFriendMessageAsync(string target, string messageId,
- params MessageBase[] chain)
+ MessageChain chain)
{
var payload = new
{
@@ -185,19 +218,19 @@ public static async Task QuoteFriendMessageAsync(string target, string m
///
///
public static async Task QuoteFriendMessageAsync(this Friend friend, string messageId,
- params MessageBase[] chain)
+ MessageChain chain)
{
return await QuoteFriendMessageAsync(friend.Id, messageId, chain);
}
///
- /// 回复群消息
+ /// 回复消息
///
///
///
///
///
- public static async Task QuoteGroupMessageAsync(string target, string messageId, params MessageBase[] chain)
+ public static async Task QuoteGroupMessageAsync(string target, string messageId, MessageChain chain)
{
var payload = new
{
@@ -217,7 +250,7 @@ public static async Task QuoteGroupMessageAsync(string target, string me
///
///
public static async Task QuoteGroupMessageAsync(this Group group, string messageId,
- params MessageBase[] chain)
+ MessageChain chain)
{
return await QuoteGroupMessageAsync(group.Id, messageId, chain);
}
@@ -231,7 +264,7 @@ public static async Task QuoteGroupMessageAsync(this Group group, string
///
///
public static async Task QuoteTempMessageAsync(string memberId, string group, string messageId,
- params MessageBase[] chain)
+ MessageChain chain)
{
var payload = new
{
@@ -252,156 +285,10 @@ public static async Task QuoteTempMessageAsync(string memberId, string g
///
///
public static async Task QuoteTempMessageAsync(this Member member, string messageId,
- params MessageBase[] chain)
- {
- return await QuoteTempMessageAsync(member.Group.Id, member.Group.Id, messageId);
- }
-
- #endregion
-
- #region Exposed overloads
-
- ///
- /// 发送好友消息
- ///
- ///
- ///
- ///
- public static async Task SendFriendMessageAsync(string target, string message)
- {
- return await SendFriendMessageAsync(target, message.Append());
- }
-
- ///
- /// 发送好友消息
- ///
- ///
- ///
- ///
- public static async Task SendFriendMessageAsync(this Friend target, string message)
- {
- return await SendFriendMessageAsync(target, message.Append());
- }
-
-
- ///
- /// 发送临时消息
- ///
- ///
- ///
- ///
- ///
- public static async Task SendTempMessageAsync(string target, string group, string message)
- {
- return await SendTempMessageAsync(target, group, message.Append());
- }
-
- ///
- /// 发送临时消息
- ///
- ///
- ///
- ///
- public static async Task SendTempMessageAsync(this Member member, string message)
- {
- return await SendTempMessageAsync(member, message.Append());
- }
-
- ///
- /// 发送群消息
- ///
- ///
- ///
- ///
- public static async Task SendGroupMessageAsync(string target, string message)
- {
- return await SendGroupMessageAsync(target, message.Append());
- }
-
- ///
- /// 发送群消息
- ///
- ///
- ///
- ///
- public static async Task SendGroupMessageAsync(this Group group, string message)
- {
- return await SendGroupMessageAsync(group, message.Append());
- }
-
- ///
- /// 引用好友消息
- ///
- ///
- ///
- ///
- ///
- public static async Task QuoteFriendMessageAsync(string target, string messageId, string message)
- {
- return await QuoteFriendMessageAsync(target, messageId, message.Append());
- }
-
- ///
- /// 引用好友消息
- ///
- ///
- ///
- ///
- ///
- public static async Task QuoteFriendMessageAsync(this Friend target, string messageId, string message)
- {
- return await QuoteFriendMessageAsync(target, messageId, message.Append());
- }
-
- ///
- /// 引用群消息
- ///
- ///
- ///
- ///
- ///
- public static async Task QuoteGroupMessageAsync(string target, string messageId, string message)
- {
- return await QuoteGroupMessageAsync(target, messageId, message.Append());
- }
-
- ///
- /// 引用群消息
- ///
- ///
- ///
- ///
- ///
- public static async Task QuoteGroupMessageAsync(this Group target, string messageId, string message)
- {
- return await QuoteGroupMessageAsync(target, messageId, message.Append());
- }
-
- ///
- /// 引用临时消息
- ///
- ///
- ///
- ///
- ///
- ///
- public static async Task QuoteTempMessageAsync(string memberId, string group, string messageId,
- string message)
- {
- return await QuoteTempMessageAsync(memberId, group, messageId, message.Append());
- }
-
- ///
- /// 引用临时消息
- ///
- ///
- ///
- ///
- ///
- public static async Task QuoteTempMessageAsync(this Member member, string messageId, string message)
+ MessageChain chain)
{
- return await QuoteTempMessageAsync(member, messageId, message.Append());
+ return await QuoteTempMessageAsync(member.Id, member.Group.Id, messageId, chain);
}
#endregion
-}
\ No newline at end of file
+}
diff --git a/Mirai.Net/Sessions/Http/Managers/RequestManager.cs b/Mirai.Net/Sessions/Http/Managers/RequestManager.cs
index 9bd7a9f..ada530b 100644
--- a/Mirai.Net/Sessions/Http/Managers/RequestManager.cs
+++ b/Mirai.Net/Sessions/Http/Managers/RequestManager.cs
@@ -1,11 +1,14 @@
-using System.Threading.Tasks;
-using Mirai.Net.Data.Events.Concretes.Request;
+using Mirai.Net.Data.Events.Concretes.Request;
using Mirai.Net.Data.Sessions;
using Mirai.Net.Data.Shared;
using Mirai.Net.Utils.Internal;
+using System.Threading.Tasks;
namespace Mirai.Net.Sessions.Http.Managers;
+///
+/// 请求管理器
+///
public static class RequestManager
{
///
diff --git a/Mirai.Net/Sessions/MiraiBot.cs b/Mirai.Net/Sessions/MiraiBot.cs
index 6ca45fa..1f92eae 100644
--- a/Mirai.Net/Sessions/MiraiBot.cs
+++ b/Mirai.Net/Sessions/MiraiBot.cs
@@ -1,13 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net.WebSockets;
-using System.Reactive.Linq;
-using System.Reactive.Subjects;
-using System.Threading.Tasks;
-using AHpx.Extensions.JsonExtensions;
-using AHpx.Extensions.StringExtensions;
-using Flurl;
+using Flurl;
+using Manganese.Text;
using Mirai.Net.Data.Events;
using Mirai.Net.Data.Events.Concretes.Message;
using Mirai.Net.Data.Exceptions;
@@ -19,6 +11,13 @@
using Mirai.Net.Sessions.Http.Managers;
using Mirai.Net.Utils.Internal;
using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.WebSockets;
+using System.Reactive.Linq;
+using System.Reactive.Subjects;
+using System.Threading.Tasks;
using Websocket.Client;
namespace Mirai.Net.Sessions;
@@ -28,6 +27,9 @@ namespace Mirai.Net.Sessions;
///
public class MiraiBot : IDisposable
{
+ ///
+ /// 销毁当前对象
+ ///
public async void Dispose()
{
await ReleaseAsync();
@@ -36,6 +38,9 @@ public async void Dispose()
#region Exposed
+ ///
+ /// 启动bot
+ ///
public async Task LaunchAsync()
{
Instance = this;
@@ -59,32 +64,16 @@ public async Task LaunchAsync()
[JsonIgnore]
internal string HttpSessionKey { get; set; }
- [JsonIgnore]
- private string _address;
[JsonIgnore]
private string _qq;
[JsonIgnore]
private WebsocketClient _client;
///
- /// mirai-api-http本地服务器地址,比如:localhost:114514
+ /// mirai-api-http本地服务器地址,比如:localhost:114514,或者构造一个ConnectConfig对象
/// 传入错误的地址将会抛出异常
///
- public string Address
- {
- get => _address.TrimEnd('/').Empty("http://").Empty("https://");
- set
- {
- if (!value.Contains(":")) throw new InvalidAddressException($"错误的地址: {value}");
-
- var split = value.Split(':');
-
- if (split.Length != 2) throw new InvalidAddressException($"错误的地址: {value}");
- if (!split.Last().IsInteger()) throw new InvalidAddressException($"错误的地址: {value}");
-
- _address = value;
- }
- }
+ public ConnectConfig Address { get; set; }
///
/// 建立连接的QQ账号
@@ -92,38 +81,56 @@ public string Address
public string QQ
{
get => _qq;
- set => _qq = value.IsIntegerOrThrow(new InvalidQQException("错误的QQ号"));
+ set => _qq = value.ThrowIfNotInt64("错误的QQ号").ToString();
}
///
/// Mirai.Net总是需要一个VerifyKey
///
public string VerifyKey { get; set; }
-
+
+ ///
+ /// 群列表
+ ///
[JsonIgnore]
- public Lazy> Groups =>
+ public Lazy> Groups =>
new(() => AccountManager.GetGroupsAsync().GetAwaiter().GetResult());
-
+
+ ///
+ /// 好友列表
+ ///
[JsonIgnore]
- public Lazy> Friends =>
+ public Lazy> Friends =>
new(() => AccountManager.GetFriendsAsync().GetAwaiter().GetResult());
#endregion
#region Handlers
+ ///
+ /// 接收到事件
+ ///
[JsonIgnore] public IObservable EventReceived => _eventReceivedSubject.AsObservable();
private readonly Subject _eventReceivedSubject = new();
+ ///
+ /// 收到消息
+ ///
[JsonIgnore] public IObservable MessageReceived => _messageReceivedSubject.AsObservable();
private readonly Subject _messageReceivedSubject = new();
+ ///
+ /// 接收到未知类型的Websocket消息
+ ///
[JsonIgnore] public IObservable UnknownMessageReceived => _unknownMessageReceived.AsObservable();
private readonly Subject _unknownMessageReceived = new();
+ ///
+ /// Websocket断开连接
+ ///
[JsonIgnore]
public IObservable DisconnectionHappened => _disconnectionHappened.AsObservable();
@@ -180,7 +187,7 @@ private async Task ReleaseAsync()
///
private async Task StartWebsocketListenerAsync()
{
- var url = $"ws://{Address}/all"
+ var url = $"ws://{Address.WebsocketAddress}/all"
.SetQueryParam("verifyKey", VerifyKey)
.SetQueryParam("qq", QQ)
.ToUri();
@@ -199,68 +206,53 @@ private async Task StartWebsocketListenerAsync()
.Where(message => message.MessageType == WebSocketMessageType.Text)
.Subscribe(message =>
{
- var type = GetRespondMessageType(message);
var data = message.Text.Fetch("data");
-
- switch (type)
+ if (data == null || data.IsNullOrEmpty())
{
- case WebsocketMessageTypes.Message:
- var receiver = ReflectionUtils.GetMessageReceiverBase(data);
-
- var messageChain = data
- .Fetch("messageChain")
- .ToJArray()
- .Select(token => ReflectionUtils.GetMessageBase(token.ToString()))
- .ToList();
-
- receiver.MessageChain = messageChain;
-
- if (receiver.MessageChain.OfType().Any(x => x.Target == Instance.QQ))
- {
- _eventReceivedSubject.OnNext(new AtEvent
- {
- Receiver = (receiver as GroupMessageReceiver)!
- });
- }
-
- _messageReceivedSubject.OnNext(receiver);
- break;
- case WebsocketMessageTypes.Event:
- _eventReceivedSubject.OnNext(ReflectionUtils.GetEventBase(data));
- break;
- case WebsocketMessageTypes.Unknown:
- _unknownMessageReceived.OnNext(data);
- break;
- default:
- throw new ArgumentOutOfRangeException();
+ throw new InvalidWebsocketReponseException("Websocket传回错误响应");
}
+
+ ProcessWebSocketData(data);
});
}
- ///
- /// 获取websocket收到的消息是什么类型的
- ///
- ///
- /// 消息,事件,未知
- private static WebsocketMessageTypes GetRespondMessageType(ResponseMessage message)
+ private void ProcessWebSocketData(string data)
{
- if (message.MessageType != WebSocketMessageType.Text || message.Text.IsNullOrEmpty())
- return WebsocketMessageTypes.Unknown;
+ var dataType = data.Fetch("type");
+ if (dataType == null || dataType.IsNullOrEmpty())
+ {
+ throw new InvalidWebsocketReponseException("Websocket传回错误的响应");
+ }
- try
+ if (dataType.Contains("Message"))
{
- var json = message.Text.Fetch("data").ToJObject();
+ var receiver = ReflectionUtils.GetMessageReceiverBase(data);
+
+ var rawChain = data.Fetch("messageChain");
+ if (rawChain == null || rawChain.IsNullOrEmpty())
+ {
+ throw new InvalidResponseException("Websocket传回错误的响应");
+ }
+
+ receiver.MessageChain = rawChain.DeserializeMessageChain();
- if (!json.ContainsKey("type"))
- return WebsocketMessageTypes.Unknown;
+ if (receiver.MessageChain.OfType().Any(x => x.Target == Instance.QQ))
+ {
+ _eventReceivedSubject.OnNext(new AtEvent
+ {
+ Receiver = (receiver as GroupMessageReceiver)!
+ });
+ }
- return json.Fetch("type").Contains("Message")
- ? WebsocketMessageTypes.Message
- : WebsocketMessageTypes.Event;
+ _messageReceivedSubject.OnNext(receiver);
+ }
+ else if (dataType.Contains("Event"))
+ {
+ _eventReceivedSubject.OnNext(ReflectionUtils.GetEventBase(data));
}
- catch
+ else
{
- return WebsocketMessageTypes.Unknown;
+ _unknownMessageReceived.OnNext(data);
}
}
diff --git a/Mirai.Net/Utils/Internal/DispatchUtils.cs b/Mirai.Net/Utils/Internal/DispatchUtils.cs
new file mode 100644
index 0000000..a702572
--- /dev/null
+++ b/Mirai.Net/Utils/Internal/DispatchUtils.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Threading.Tasks;
+
+namespace Mirai.Net.Utils.Internal;
+
+///
+/// 调度工具类
+///
+public static class DispatchUtils
+{
+ ///
+ /// 在等待指定的时间后执行异步操作
+ ///
+ ///
+ ///
+ public static void ExecuteScheduledActionAsync(TimeSpan duration, Func action)
+ {
+ Task.Run(async () =>
+ {
+ await Task.Delay(duration);
+ await action();
+ });
+ }
+
+ ///
+ /// 在等待指定的时间后执行异步操作
+ ///
+ ///
+ ///
+ public static void ExecuteScheduledActionAsync(int duration, Func action)
+ {
+ ExecuteScheduledActionAsync(TimeSpan.FromMilliseconds(duration), action);
+ }
+
+ ///
+ /// 在等待指定的事件后执行同步操作
+ ///
+ ///
+ ///
+ public static void ExecuteScheduledAction(TimeSpan duration, Action action)
+ {
+ Task.Run(async () =>
+ {
+ await Task.Delay(duration);
+ action();
+ });
+ }
+
+ ///
+ /// 在等待指定的时间后执行同步操作
+ ///
+ ///
+ ///
+ public static void ExecuteScheduledAction(int duration, Action action)
+ {
+ ExecuteScheduledAction(TimeSpan.FromMilliseconds(duration), action);
+ }
+}
\ No newline at end of file
diff --git a/Mirai.Net/Utils/Internal/EnumeratedTypeUtils.cs b/Mirai.Net/Utils/Internal/EnumeratedTypeUtils.cs
index 3e187ab..40baf4a 100644
--- a/Mirai.Net/Utils/Internal/EnumeratedTypeUtils.cs
+++ b/Mirai.Net/Utils/Internal/EnumeratedTypeUtils.cs
@@ -4,7 +4,7 @@
namespace Mirai.Net.Utils.Internal;
-public static class EnumeratedTypeUtils
+internal static class EnumeratedTypeUtils
{
///
/// 获取某枚举值的Description attribute值,如果没有这个特性则直接返回该值的ToString
diff --git a/Mirai.Net/Utils/Internal/ExceptionUtils.cs b/Mirai.Net/Utils/Internal/ExceptionUtils.cs
index 864fb12..e17a722 100644
--- a/Mirai.Net/Utils/Internal/ExceptionUtils.cs
+++ b/Mirai.Net/Utils/Internal/ExceptionUtils.cs
@@ -1,12 +1,10 @@
-using System;
+using Manganese.Text;
using System.Collections.Generic;
using System.Linq;
-using AHpx.Extensions.JsonExtensions;
-using AHpx.Extensions.StringExtensions;
namespace Mirai.Net.Utils.Internal;
-public static class ExceptionUtils
+internal static class ExceptionUtils
{
///
/// 获取状态码对应的原因
@@ -15,24 +13,25 @@ public static class ExceptionUtils
///
internal static string OfErrorMessage(this string json)
{
- var code = json.Fetch("code").IsIntegerOrThrow(new ArgumentException("错误的状态码"));
+ // todo: use is integer
+ var code = json.Fetch("code")?.ThrowIfNotInt64("错误的状态码");
- var vocabulary = new Dictionary
+ return code switch
{
- { "0", "正确" },
- { "1", "错误的verify key" },
- { "2", "指定的Bot不存在" },
- { "3", "Session失效或不存在" },
- { "4", "Session未认证(未激活)" },
- { "5", "发送消息目标不存在(指定对象不存在)" },
- { "6", "指定文件不存在" },
- { "10", "Bot没有对应操作的限权" },
- { "20", "Bot被禁言" },
- { "30", "消息过长" },
- { "400", "错误的访问" },
- { "500", "上传文件错误" }
+ 0 => "成功", // Success : StateCode(0, "success") // 成功
+ 1 => "错误的verify key", // AuthKeyFail : StateCode(1, "Auth Key错误")
+ 2 => "指定的Bot不存在", // NoBot : StateCode(2, "指定Bot不存在")
+ 3 => "Session失效或不存在", // IllegalSession : StateCode(3, "Session失效或不存在")
+ 4 => "Session未认证", // NotVerifySession : StateCode(4, "Session未认证")
+ 5 => "指定对象不存在", // NoElement : StateCode(5, "指定对象不存在")
+ 6 => "指定操作不支持", // NoOperateSupport : StateCode(6, "指定操作不支持")
+ 10 => "Bot没有对应操作的权限", // PermissionDenied : StateCode(10, "无操作权限")
+ 20 => "Bot被禁言", // BotMuted : StateCode(20, "Bot被禁言")
+ 30 => "消息过长", // MessageTooLarge : StateCode(30, "消息过长")
+ 400 => "无效参数", // InvalidParameter : StateCode(400, "无效参数")
+ 500 => "内部错误", // class InternalError() : StateCode(500, "")
+ _ => null // default case if code does not match any known codes
};
-
- return vocabulary.FirstOrDefault(x => x.Key == code).Value;
}
+
}
\ No newline at end of file
diff --git a/Mirai.Net/Utils/Internal/MiraiHttpUtils.cs b/Mirai.Net/Utils/Internal/MiraiHttpUtils.cs
index 891571f..6dbbbe5 100644
--- a/Mirai.Net/Utils/Internal/MiraiHttpUtils.cs
+++ b/Mirai.Net/Utils/Internal/MiraiHttpUtils.cs
@@ -1,16 +1,29 @@
-using System.Threading.Tasks;
-using AHpx.Extensions.JsonExtensions;
-using AHpx.Extensions.StringExtensions;
-using Flurl;
+using Flurl;
using Flurl.Http;
+using Manganese.Text;
using Mirai.Net.Data.Exceptions;
using Mirai.Net.Data.Sessions;
using Mirai.Net.Sessions;
+using Newtonsoft.Json;
+using System;
+using System.Threading.Tasks;
+using NullValueHandling = Newtonsoft.Json.NullValueHandling;
namespace Mirai.Net.Utils.Internal;
-internal static class MiraiHttpUtils
+///
+/// 用户自定义错误处理
+///
+public delegate void ErrorHandler(Exception ex);
+///
+/// 由于特定插件有自定义Endpoint的需求,因此有必要将PostJsonAsync与GetAsync整体暴露为public
+///
+public static class MiraiHttpUtils
{
+ ///
+ /// 用户自定义错误处理器
+ ///
+ public static ErrorHandler HttpErrorHandler { get; set; }
#region Guarantee
///
@@ -22,21 +35,23 @@ internal static void EnsureSuccess(this string json, string appendix = null)
{
var obj = json.ToJObject();
- if (obj.ContainsKey("code"))
- {
- var code = obj.Fetch("code");
- if (code != "0")
- {
- var message = $"原因: {json.OfErrorMessage()}";
+ var code = obj["code"]?.ToString();
+
+ if (code is null or "0") return;
- if (appendix.IsNotNullOrEmpty())
- message += $"\r\n备注: {appendix}";
- else
- message += $"\r\n备注: {MiraiBot.Instance.ToJsonString()}";
+ var message = $"原因: {json.OfErrorMessage()}\r\n备注: ";
+ message += string.IsNullOrEmpty(appendix)
+ ? MiraiBot.Instance.ToJsonString()
+ : appendix;
- throw new InvalidResponseException(message);
+ var exception = new InvalidResponseException(message)
+ {
+ Data = {
+ ["code"] = code,
+ ["msg"] = obj.TryGetValue("msg", out var value) ? value.ToString() : null
}
- }
+ };
+ throw exception;
}
#endregion
@@ -48,24 +63,40 @@ internal static void EnsureSuccess(this string json, string appendix = null)
///
/// 是否添加session头
///
- internal static async Task GetAsync(string url, bool withSessionKey = true)
+ public static async Task GetAsync(string url, bool withSessionKey = true)
{
- var result = withSessionKey
- ? await url
- .WithHeader("Authorization", $"session {MiraiBot.Instance.HttpSessionKey}")
- .GetAsync()
- : await url.GetAsync();
+ try
+ {
+ var result = withSessionKey
+ ? await url
+ .WithHeader("Authorization", $"session {MiraiBot.Instance.HttpSessionKey}")
+ .GetAsync()
+ : await url.GetAsync();
- var re = await result.GetStringAsync();
- re.EnsureSuccess($"url={url}");
+ var re = await result.GetStringAsync();
+ re.EnsureSuccess($"url={url}");
- return re;
+ return re;
+ }
+ catch (Exception e)
+ {
+ if (HttpErrorHandler != null)
+ {
+ e.Data["method"] = "get";
+ e.Data["url"] = url;
+ HttpErrorHandler.Invoke(e); // 如果错误处理器不为 null,则调用
+ }
+
+ else
+ throw; // 否则,重新抛出异常
+ return null;
+ }
}
internal static async Task GetAsync(this HttpEndpoints endpoints, object extra = null,
bool withSessionKey = true)
{
- var url = $"http://{MiraiBot.Instance.Address}/{endpoints.GetDescription()}";
+ var url = $"http://{MiraiBot.Instance.Address.HttpAddress}/{endpoints.GetDescription()}";
if (extra != null)
url = url.SetQueryParams(extra);
@@ -79,18 +110,41 @@ internal static async Task GetAsync(this HttpEndpoints endpoints, object
///
/// 加入Authentication: session xxx 请求头
///
- internal static async Task PostJsonAsync(string url, object json, bool withSessionKey = true)
+ public static async Task PostJsonAsync(string url, object json, bool withSessionKey = true)
{
- var result = withSessionKey
- ? await url
- .WithHeader("Authorization", $"session {MiraiBot.Instance.HttpSessionKey}")
- .PostJsonAsync(json)
- : await url.PostJsonAsync(json);
-
- var re = await result.GetStringAsync();
- re.EnsureSuccess($"url={url}\r\npayload={json.ToJsonString()}");
+ try
+ {
+ var result = withSessionKey
+ ? await url
+ .WithHeader("Authorization", $"session {MiraiBot.Instance.HttpSessionKey}")
+ .PostStringAsync(json.ToJsonString(new JsonSerializerSettings
+ {
+ NullValueHandling = NullValueHandling.Ignore
+ }))
+ : await url.PostStringAsync(json.ToJsonString(new JsonSerializerSettings
+ {
+ NullValueHandling = NullValueHandling.Ignore
+ }));
+
+ var re = await result.GetStringAsync();
+ re.EnsureSuccess($"url={url}\r\npayload={json.ToJsonString()}");
+
+ return re;
+ }
+ catch (Exception e)
+ {
+ if (HttpErrorHandler != null)
+ {
+ e.Data["method"] = "post";
+ e.Data["url"] = url;
+ e.Data["json"] = json;
+ HttpErrorHandler.Invoke(e); // 如果错误处理器不为 null,则调用
+ }
- return re;
+ else
+ throw; // 否则,重新抛出异常
+ return null;
+ }
}
///
@@ -102,7 +156,7 @@ internal static async Task PostJsonAsync(string url, object json, bool w
internal static async Task PostJsonAsync(this HttpEndpoints endpoint, object json,
bool withSessionKey = true)
{
- var url = $"http://{MiraiBot.Instance.Address}/{endpoint.GetDescription()}";
+ var url = $"http://{MiraiBot.Instance.Address.HttpAddress}/{endpoint.GetDescription()}";
var result = await PostJsonAsync(url, json, withSessionKey);
return result;
diff --git a/Mirai.Net/Utils/Internal/ReflectionUtils.cs b/Mirai.Net/Utils/Internal/ReflectionUtils.cs
index 287aa28..5b08eec 100644
--- a/Mirai.Net/Utils/Internal/ReflectionUtils.cs
+++ b/Mirai.Net/Utils/Internal/ReflectionUtils.cs
@@ -1,23 +1,26 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using AHpx.Extensions.JsonExtensions;
+using Manganese.Text;
using Mirai.Net.Data.Events;
+using Mirai.Net.Data.Events.Concretes;
using Mirai.Net.Data.Messages;
using Mirai.Net.Data.Messages.Concretes;
+using Mirai.Net.Data.Messages.Receivers;
+using Mirai.Net.Utils.Scaffolds;
using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
namespace Mirai.Net.Utils.Internal;
-public static class ReflectionUtils
+internal static class ReflectionUtils
{
///
/// 获取某个命名空间下所有类的默认实例
///
///
///
- public static IEnumerable GetDefaultInstances(string @namespace) where T : class
+ internal static IEnumerable GetDefaultInstances(string @namespace) where T : class
{
return Assembly
.GetExecutingAssembly()
@@ -25,28 +28,106 @@ public static IEnumerable GetDefaultInstances(string @namespace) where T :
.Where(type => type.FullName != null)
.Where(type => type.FullName.Contains(@namespace))
.Where(type => !type.IsAbstract)
- .Select(type => Activator.CreateInstance(type) as T);
+ .Select(type =>
+ {
+ if (Activator.CreateInstance(type) is T instance)
+ {
+ return instance;
+ }
+
+ return null;
+ })
+ .Where(i => i != null);
+ }
+
+ #region Type Cache
+
+ ///
+ /// 将指定的类型集合转换为字典,
+ /// 不需要在每次获取类型时调用类型的GetType方法, 提升每次获取实例类型时的性能。
+ ///
+ /// 实例集合
+ /// 作为字典键的枚举类型
+ /// 作为字典值:枚举值对应类型的Type
+ ///
+ private static Dictionary InitTypeHashSet(IEnumerable enumerable)
+ where T : Enum
+ where R : class
+ {
+ var dict = new Dictionary();
+
+ foreach (var item in enumerable)
+ {
+ T key;
+ Type type;
+ switch (item)
+ {
+ case MessageReceiverBase receiverBase:
+ key = (T) Enum.Parse(typeof(T), receiverBase.Type.ToString());
+ type = receiverBase.GetType();
+ break;
+ case MessageBase messageBase:
+ key = (T) Enum.Parse(typeof(T), messageBase.Type.ToString());
+ type = messageBase.GetType();
+ break;
+ case EventBase eventBase:
+ key = (T) Enum.Parse(typeof(T), eventBase.Type.ToString());
+ type = eventBase.GetType();
+ break;
+ default:
+ throw new ArgumentException("该方法不支持此类型使用!", typeof(R).FullName);
+ }
+
+ if (!dict.ContainsKey(key))
+ {
+ dict.Add(key, type);
+ }
+ }
+
+ return dict;
}
-
+
///
/// 默认消息接收器实例
///
private static readonly IEnumerable MessageReceiverBases =
GetDefaultInstances(
"Mirai.Net.Data.Messages.Receivers");
-
+
+ ///
+ /// 默认消息接收器类型字典(K: 接收器的类别, V: 实例的Type)
+ ///
+ private static readonly Dictionary MessageReceiverTypeDict =
+ InitTypeHashSet(MessageReceiverBases);
+
+
///
/// 默认消息实例
///
private static readonly IEnumerable MessageBases =
GetDefaultInstances("Mirai.Net.Data.Messages.Concretes");
+ ///
+ /// 默认消息实例类型字典(K: 消息的类别, V: 实例的Type)
+ ///
+ private static readonly Dictionary MessageBaseTypeDict =
+ InitTypeHashSet(MessageBases);
+
+
///
/// 默认事件实例
///
private static readonly IEnumerable EventBases =
GetDefaultInstances("Mirai.Net.Data.Events.Concretes");
-
+
+ ///
+ /// 默认事件实例类型字典(K: 事件类别, V: 实例Type)
+ ///
+ private static readonly Dictionary EventTypeDict = InitTypeHashSet(EventBases);
+
+ #endregion
+
+
///
/// 根据json动态解析对应的消息子类
///
@@ -54,42 +135,49 @@ public static IEnumerable GetDefaultInstances(string @namespace) where T :
///
internal static MessageBase GetMessageBase(string data)
{
- var root = JsonConvert.DeserializeObject(data);
-
- if (root!.Type == Messages.Quote)
+ try
{
- var quote = JsonConvert.DeserializeObject(data);
+ var raw = JsonConvert.DeserializeObject(data);
- quote!.Origin = data.FetchJToken("origin")
- .Select(x => GetMessageBase(x.ToString()))
- .ToArray();
-
- return quote;
- }
+ if (raw!.Type == Messages.Quote)
+ {
+ var quote = JsonConvert.DeserializeObject(data);
- if (root!.Type == Messages.Forward)
- {
- var forward = JsonConvert.DeserializeObject(data);
+ quote!.Origin = data.FetchJToken("origin")!
+ .Select(x => GetMessageBase(x.ToString()))
+ .ToArray();
- forward!.NodeList = data.FetchJToken("nodeList")
- .Select(x =>
- {
- var node = x.ToObject();
- node!.MessageChain = x.FetchJToken("messageChain").Select(z => GetMessageBase(z.ToString()))
- .ToArray();
+ return quote;
+ }
- return node;
- })
- .ToArray();
+ if (raw!.Type == Messages.Forward)
+ {
+ var forward = JsonConvert.DeserializeObject(data);
- return forward;
- }
+ forward!.NodeList = data.FetchJToken("nodeList")!
+ .Select(x =>
+ {
+ var node = x.ToObject();
+ node!.MessageChain = x.Fetch("messageChain")!.DeserializeMessageChain();
+
+ return node;
+ })
+ .ToArray();
- return JsonConvert.DeserializeObject(data,
- MessageBases.First(message => message.Type == root!.Type)
- .GetType()) as MessageBase;
+ return forward;
+ }
+
+ // 因为有异常捕获来处理转换失败的情况, 如果获取不到类型那一定得抛出异常, 所以此处直接用索引获取实例类型.
+ return JsonConvert.DeserializeObject(data, MessageBaseTypeDict[raw!.Type]) as MessageBase;
+ }
+ catch
+ {
+ var re = JsonConvert.DeserializeObject(data);
+ re!.RawJson = data;
+ return re;
+ }
}
-
+
///
/// 根据json动态解析正确的消息接收器子类
///
@@ -97,11 +185,21 @@ internal static MessageBase GetMessageBase(string data)
///
internal static MessageReceiverBase GetMessageReceiverBase(string data)
{
- var root = JsonConvert.DeserializeObject(data);
+ try
+ {
+ var raw = JsonConvert.DeserializeObject(data);
- return JsonConvert.DeserializeObject(data,
- MessageReceiverBases.First(receiver => receiver.Type == root!.Type)
- .GetType()) as MessageReceiverBase;
+ // 因为有异常捕获来处理转换失败的情况, 如果获取不到类型那一定得抛出异常, 所以此处直接用索引获取.
+ var type = MessageReceiverTypeDict[raw!.Type];
+
+ return JsonConvert.DeserializeObject(data, type) as MessageReceiverBase;
+ }
+ catch
+ {
+ var re = JsonConvert.DeserializeObject(data);
+ re!.RawJson = data;
+ return re;
+ }
}
///
@@ -111,10 +209,30 @@ internal static MessageReceiverBase GetMessageReceiverBase(string data)
///
internal static EventBase GetEventBase(string data)
{
- var root = JsonConvert.DeserializeObject(data);
+ try
+ {
+ var raw = JsonConvert.DeserializeObject(data);
- return JsonConvert.DeserializeObject(data,
- EventBases.First(message => message.Type == root!.Type)
- .GetType()) as EventBase;
+ // 因为有异常捕获来处理转换失败的情况, 如果获取不到类型那一定得抛出异常, 所以此处直接用索引获取实例的类型.
+ return JsonConvert.DeserializeObject(data, EventTypeDict[raw!.Type]) as EventBase;
+ }
+ catch
+ {
+ var re = JsonConvert.DeserializeObject(data);
+ re!.RawJson = data;
+ return re;
+ }
+ }
+
+ ///
+ /// 反序列化消息链
+ ///
+ ///
+ ///
+ internal static MessageChain DeserializeMessageChain(this string data)
+ {
+ return data.ToJArray()
+ .Select(token => ReflectionUtils.GetMessageBase(token.ToString()))
+ .ToMessageChain();
}
}
\ No newline at end of file
diff --git a/Mirai.Net/Utils/Scaffolds/CommandScaffold.cs b/Mirai.Net/Utils/Scaffolds/CommandScaffold.cs
deleted file mode 100644
index 9b12787..0000000
--- a/Mirai.Net/Utils/Scaffolds/CommandScaffold.cs
+++ /dev/null
@@ -1,424 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using AHpx.Extensions.StringExtensions;
-using Mirai.Net.Data.Commands;
-using Mirai.Net.Data.Exceptions;
-using Mirai.Net.Data.Messages;
-using Mirai.Net.Data.Messages.Concretes;
-using Mirai.Net.Data.Modules;
-using Mirai.Net.Modules;
-
-namespace Mirai.Net.Utils.Scaffolds;
-
-public static class CommandScaffold
-{
- ///
- /// 解析命令到实体类
- ///
- ///
- ///
- ///
- ///
- ///
- public static T ParseCommand(this string origin) where T : class, new()
- {
- origin = origin.Trim();
-
- var re = new T();
- var type = re.GetType();
- var commandInfo = type.GetCustomAttribute();
-
- var properties = type.GetProperties();
- var args = properties
- .Select(x => (x, x.GetCustomAttribute()))
- .Where(x => x.Item2 != null)
- .ToList();
-
- #region Pre check
-
- if (!HasValidIdentifier(commandInfo, origin))
- throw new InvalidCommandException($"此字符串无法解析为命令:\r\n{origin}");
-
- // if (args.Count(x => x.Item2.IsDefault) > 1)
- // throw new InvalidCommandEntityException($"只能有一个默认参数");
-
- #endregion
-
- foreach (var (propertyInfo, argumentInfo) in args)
- {
- var argumentSyntax = $"{commandInfo.Separator}{argumentInfo.Name}";
- var argumentMeta = $"{argumentInfo.Name}/{propertyInfo.Name}";
-
- var propertyType = propertyInfo.PropertyType;
-
- if (origin.Split(' ').Count(x => x == argumentSyntax) > 1)
- throw new InvalidCommandException($"命令参数{argumentInfo.Name}重复");
-
- // if (argumentInfo.IsDefault && !origin.Contains(argumentSyntax))
- // {
- // var commandSyntax = $"{commandInfo.Identifier}{commandInfo.Name}";
- //
- // var left = commandSyntax.Length;
- // var right = origin.Contains(commandInfo.Separator)
- // ? origin.IndexOf(commandInfo.Separator, left, StringComparison.Ordinal) - left
- // : origin.Length - left;
- //
- // propertyInfo.SetValue(re, origin.Substring(left, right));
- //
- // continue;
- // }
-
- switch (argumentInfo.IsRequired)
- {
- case true when argumentInfo.Default is not null:
- throw new InvalidCommandEntityException(
- $"命令实体不能同时设置为必须参数和默认值: {argumentMeta}");
- case true when !origin.Contains(argumentSyntax):
- throw new InvalidCommandException($"缺失必要参数: {argumentMeta}");
- case true when propertyInfo.PropertyType == typeof(bool):
- // throw new InvalidCommandException($"选项参数{argumentMeta}不可以是必须参数");
- // case true when argumentInfo.IsDefault:
- throw new InvalidCommandException($"必须参数{argumentMeta}不可以是默认参数");
- case false when argumentInfo.Default is not null:
- propertyInfo.SetValue(re, argumentInfo.Default);
- break;
- }
-
- switch (origin.Contains(argumentSyntax))
- {
- case true when propertyType == typeof(bool):
- propertyInfo.SetValue(re, true);
- break;
- case true when propertyType == typeof(IEnumerable) ||
- propertyType == typeof(List) ||
- propertyType == typeof(string[]):
-
- var arg = GetMiddleContent(commandInfo, origin, argumentSyntax)
- .Split(' ')
- .Where(x => x.IsNotNullOrEmpty()).ToList();
-
- arg.RemoveAt(0);
-
- if (propertyType == typeof(string[]))
- {
- propertyInfo.SetValue(re, arg.ToArray());
- break;
- }
- propertyInfo.SetValue(re, arg);
- break;
- case true when propertyType == typeof(string):
- propertyInfo.SetValue(re, GetMiddleContent(commandInfo, origin, argumentSyntax));
- break;
- case true when propertyType == typeof(int) ||
- propertyType == typeof(long):
- var intArg = GetMiddleContent(commandInfo, origin, argumentSyntax)
- .IsIntegerOrThrow(new InvalidCommandException($"参数{argumentMeta}必须为整数"));
-
- Console.WriteLine(propertyType == typeof(int));
- if (int.TryParse(intArg, out var outInt))
- {
- propertyInfo.SetValue(re, outInt);
- break;
- }
-
- if (long.TryParse(intArg, out var outLong))
- propertyInfo.SetValue(re, outLong);
- break;
- case true when propertyType == typeof(double):
- var doubleArg = GetMiddleContent(commandInfo, origin, argumentSyntax);
-
- if (!double.TryParse(doubleArg, out var d))
- throw new InvalidCommandException($"参数{argumentMeta}必须为双精度浮点数");
-
- propertyInfo.SetValue(re, d);
- break;
- }
- }
-
- return re;
- }
-
- public static bool CanExecute(this string origin) where T : class, new()
- {
- var entity = new T();
- var type = entity.GetType();
- var properties = type.GetProperties();
- var commandInfo = type.GetCustomAttribute();
- var args = properties
- .Select(x => (x, x.GetCustomAttribute()))
- .Where(x => x.Item2 != null)
- .ToList();
-
- if (!HasValidIdentifier(commandInfo, origin))
- return false;
-
- // if (args.Count(x => x.Item2.IsDefault) > 1)
- // return false;
-
- foreach (var (propertyInfo, argumentInfo) in args)
- {
- var argumentSyntax = $"{commandInfo.Separator}{argumentInfo.Name}";
-
- var propertyType = propertyInfo.PropertyType;
-
- if (origin.Split(' ').Count(x => x == argumentSyntax) > 1)
- return false;
-
- switch (argumentInfo.IsRequired)
- {
- case true when argumentInfo.Default is not null:
- return false;
- case true when !origin.Contains(argumentSyntax):
- return false;
- case true when propertyInfo.PropertyType == typeof(bool):
- return false;
- // case true when argumentInfo.IsDefault:
- // return false;
- }
-
- switch (origin.Contains(argumentSyntax))
- {
- case true when propertyType == typeof(int) ||
- propertyType == typeof(long):
- var intArg = GetMiddleContent(commandInfo, origin, argumentSyntax);
-
- if (intArg.IsNotInteger())
- return false;
-
- return int.TryParse(intArg, out _) || long.TryParse(intArg, out _);
- case true when propertyType == typeof(double):
- var doubleArg = GetMiddleContent(commandInfo, origin, argumentSyntax);
-
- return double.TryParse(doubleArg, out _);
- }
- }
-
- return true;
- }
-
- ///
- /// 判断某命令的起始符是否合法
- ///
- ///
- ///
- ///
- private static bool HasValidIdentifier(CommandEntityAttribute commandInfo, string origin)
- {
- var syntax = commandInfo.Alias
- .Aggregate($"{commandInfo.Identifier}{commandInfo.Name}", (a, b) => $"{a};{commandInfo.Identifier}{b}")
- .Split(';');
-
- return syntax.Any(s =>
- {
- var index = origin.IndexOf(commandInfo.Separator, 1, StringComparison.Ordinal);
-
- if (index == -1)
- return origin.Trim() == s;
-
- return origin.Substring(0, index).Trim() == s;
- });
- }
-
- ///
- /// 获取两个参数之间的内容
- ///
- ///
- ///
- ///
- ///
- private static string GetMiddleContent(CommandEntityAttribute entity, string origin, string syntax)
- {
- var left = origin.IndexOf(syntax, StringComparison.Ordinal);
- var right = origin.IndexOf(entity.Separator, left + 1, StringComparison.Ordinal);
- var rawArg = right != -1 ? origin.Substring(left, right - left) : origin.Substring(left);
-
- rawArg = rawArg.Empty(syntax).Trim();
- return rawArg;
- }
-
- ///
- /// 消息链是否可以执行命令
- ///
- ///
- ///
- ///
- [Obsolete]
- public static bool CanExecute(this IEnumerable originalChain, CommandTriggerAttribute trigger)
- {
- return CanExecute(originalChain, trigger, out _);
- }
-
- ///
- /// 消息链是否可以执行命令
- ///
- ///
- ///
- /// 哪个消息是可以执行的
- ///
- [Obsolete]
- public static bool CanExecute(this IEnumerable originalChain, CommandTriggerAttribute trigger,
- out MessageBase executedBy)
- {
- var chain = originalChain.ToList();
- if (chain.Any(x => x.Type == Messages.Plain))
- foreach (var message in chain.OfType())
- if (trigger.IsCommand(message.Text))
- {
- executedBy = message;
- return true;
- }
-
- trigger.EqualName = false;
- foreach (var s in chain.Where(s => trigger.IsCommand(s.ToJsonString())))
- {
- executedBy = s;
- return true;
- }
-
- executedBy = null;
- return false;
- }
-
- ///
- /// 判断一个字符串是否为命令
- ///
- ///
- ///
- ///
- [Obsolete]
- public static bool IsCommand(this CommandTriggerAttribute trigger, string s)
- {
- var expectation = $"{trigger.Prefix}{trigger.Name}";
-
- return trigger.EqualName ? s.StartsWith(expectation) : s.Contains(expectation);
- }
-
- ///
- /// 解析命令,Dictionary的key为参数名,value为参数值
- ///
- ///
- ///
- ///
- [Obsolete]
- public static IDictionary ParseCommand(this CommandTriggerAttribute trigger, string s)
- {
- var split = s
- .Empty($"{trigger.Prefix}{trigger.Name}")
- .Trim().Split(' ')
- .Where(x => x.IsNotNullOrEmpty())
- .ToList();
-
- var re = new Dictionary();
- var indexes = new List();
-
- split
- .Where(x => x.StartsWith(trigger.ArgsSeparator))
- .ToList()
- .ForEach(x => indexes.Add(split.IndexOf(x)));
-
- foreach (var index in indexes)
- {
- int next;
- if (indexes.IndexOf(index) + 1 >= indexes.Count)
- next = split.Count - 1;
- else
- next = indexes[indexes.IndexOf(index) + 1];
-
- var range = next != split.Count - 1
- ? split.GetRange(index, next - index)
- : split.GetRange(index, split.Count - index);
-
- re.Add(range.First().TrimStart(trigger.ArgsSeparator.ToCharArray()),
- range.GetRange(1, range.Count - 1).ToArray());
- }
-
- return re;
- }
-
- ///
- /// 解析命令
- ///
- ///
- ///
- ///
- [Obsolete]
- public static IDictionary ParseCommand(this ICommandModule commandModule, string command)
- {
- return commandModule.GetCommandTrigger().ParseCommand(command);
- }
-
- ///
- /// 检查某命令是否有参数
- ///
- ///
- ///
- ///
- [Obsolete]
- public static bool HasParameters(this CommandTriggerAttribute trigger, string s)
- {
- return trigger.ParseCommand(s).Count != 0;
- }
-
- ///
- /// 获取本模块的CommandTrigger
- ///
- ///
- ///
- [Obsolete]
- public static CommandTriggerAttribute GetCommandTrigger(this ICommandModule commandModule)
- {
- return commandModule.GetType().GetMethod(nameof(commandModule.Execute))!
- .GetCustomAttribute();
- }
-
- ///
- /// 执行集合内的全部命令模块,除非它没开启
- ///
- ///
- ///
- [Obsolete]
- public static void ExecuteCommandModules(this MessageReceiverBase receiver, IEnumerable modules)
- {
- foreach (var module in modules.Where(x => x.IsEnable is not false))
- if (receiver.MessageChain.CanExecute(module.GetCommandTrigger(), out var message))
- module.Execute(receiver, message);
- }
-
- ///
- /// 加载指定命名空间的命令模块
- ///
- [Obsolete]
- public static IEnumerable LoadCommandModules(string space)
- {
- var assembly = Assembly.GetEntryAssembly();
- var types =assembly.GetTypes()
- .Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface)
- .Where(x => x.GetInterfaces().Any(x => x == typeof(ICommandModule)))
- .Where(x => x!.FullName!.Contains(space))
- .ToList();
-
- foreach (var type in types) yield return Activator.CreateInstance(type) as ICommandModule;
- }
-
- ///
- /// 加载与某模块同命名空间的所有模块
- ///
- /// 某模块
- ///
- [Obsolete]
- public static IEnumerable LoadCommandModules() where T : ICommandModule
- {
- var basic = typeof(T);
-
- var types = Assembly.GetAssembly(basic).GetTypes()
- .Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface)
- .Where(x => x.GetInterfaces().Any(x => x == typeof(ICommandModule)))
- .Where(x => x!.FullName!.Contains(basic.Namespace!))
- .ToList();
-
- foreach (var type in types) yield return Activator.CreateInstance(type) as ICommandModule;
- }
-}
\ No newline at end of file
diff --git a/Mirai.Net/Utils/Scaffolds/MessageChain.cs b/Mirai.Net/Utils/Scaffolds/MessageChain.cs
new file mode 100644
index 0000000..4928a78
--- /dev/null
+++ b/Mirai.Net/Utils/Scaffolds/MessageChain.cs
@@ -0,0 +1,249 @@
+using Manganese.Array;
+using Manganese.Text;
+using Mirai.Net.Data.Messages.Concretes;
+using Mirai.Net.Data.Messages.Receivers;
+using Mirai.Net.Utils.Scaffolds;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+// ReSharper disable once CheckNamespace
+namespace Mirai.Net.Data.Messages;
+
+///
+/// 消息链
+///
+public partial class MessageChain : List
+{
+ ///
+ /// AddRange
+ ///
+ ///
+ public MessageChain(IEnumerable collection) : base(collection)
+ {
+ }
+
+ ///
+ ///
+ ///
+ public MessageChain() : base()
+ {
+ }
+
+ ///
+ /// 运行时安全的Mirai码
+ ///
+ public string MiraiCode
+ {
+ get
+ {
+ System.Text.StringBuilder builder = new();
+
+ this.ForEach(x =>
+ {
+ try
+ {
+ builder.Append(x.SerializeToMiraiCode());
+ }
+ catch
+ {}
+ });
+
+ return builder.ToString();
+ }
+ }
+
+ ///
+ /// 获取消息链中的纯文本消息
+ ///
+ /// 如果没有文本消息返回空字符串
+ public string GetPlainMessage()
+ {
+ var plain = this.OfType().ToList();
+ if (!plain.Any())
+ return string.Empty;
+
+ return plain.Select(x => x.Text).JoinToString("");
+ }
+
+#nullable enable
+
+ ///
+ /// 获取该消息的消息来源 如果有多个来源返回最后一个 如果没有来源则返回null
+ ///
+ ///
+ public SourceMessage? GetSourceMessage() => this.OfType().LastOrDefault();
+
+ ///
+ /// 获取该消息的消息引用 如果有多个引用返回最后一个 如果没有引用则返回null
+ ///
+ ///
+ public QuoteMessage? GetQuoteMessage() => this.OfType().LastOrDefault();
+
+#nullable disable
+
+ ///
+ /// 获取消息链中的文本消息并且保持原有连贯性
+ ///
+ /// 如果没有文本消息返回空列表
+ public List GetSeparatedPlainMessage()
+ {
+ var plain = this.OfType().ToList();
+ if (!plain.Any())
+ return new List();
+
+ return plain.Select(x => x.Text).ToList();
+ }
+
+ ///
+ /// 将本消息链发送到指定接收器
+ ///
+ ///
+ ///
+ public async Task SendToAsync(GroupMessageReceiver receiver)
+ {
+ return await receiver.SendMessageAsync(this);
+ }
+
+ ///
+ /// 将本消息链发送到指定接收器
+ ///
+ ///
+ ///
+ public async Task SendToAsync(FriendMessageReceiver receiver)
+ {
+ return await receiver.SendMessageAsync(this);
+ }
+
+ ///
+ /// 将本消息链发送到指定接收器
+ ///
+ ///
+ ///
+ public async Task SendToAsync(TempMessageReceiver receiver)
+ {
+ return await receiver.SendMessageAsync(this);
+ }
+
+ ///
+ /// 将该消息链序列化为mirai码 不会捕获异常
+ ///
+ ///
+ public string SerializeToMiraiCode()
+ {
+ System.Text.StringBuilder builder = new();
+
+ this.ForEach(x => builder.Append(x.SerializeToMiraiCode()));
+
+ return builder.ToString();
+ }
+
+ ///
+ /// 自动转换单个消息为消息链
+ ///
+ ///
+ ///
+ public static implicit operator MessageChain(MessageBase messageBase)
+ {
+ return messageBase.ToMessageChain();
+ }
+
+ ///
+ /// 转换string为单文本消息链
+ ///
+ ///
+ ///
+ public static implicit operator MessageChain(string message)
+ {
+ return new PlainMessage(message).ToMessageChain();
+ }
+
+ ///
+ /// 拼接两个消息链
+ ///
+ ///
+ ///
+ ///
+ public static MessageChain operator +(MessageChain chain1, MessageChain chain2)
+ {
+ var chain = new MessageChain();
+ chain.AddRange(chain1);
+ chain.AddRange(chain2);
+ return chain;
+ }
+
+ ///
+ /// 拼接消息链和消息
+ ///
+ ///
+ ///
+ ///
+ public static MessageChain operator +(MessageChain chain, MessageBase msg)
+ {
+ chain.Add(msg);
+ return chain;
+ }
+
+ ///
+ /// 返回两个消息链是否相等
+ ///
+ ///
+ ///
+ ///
+ public static bool operator ==(MessageChain left, MessageChain right)
+ {
+ left = left.Where(x => x is not SourceMessage).ToMessageChain();
+
+ right = right.Where(x => x is not SourceMessage).ToMessageChain();
+
+ if (left.Count != right.Count) return false;
+
+ for (int i = 0; i < left.Count; i++)
+ {
+ if (left[i].Type != right[i].Type) return false;
+
+ // 这段代码用了一种极其诡异的方法判断是否相等
+ // 首先检查能否转换为图片消息或者语音消息然后挨个判断四个属性 都不相等就返回false 有一个相等就返回true
+ // 然后看不能转换的时候利用record直接判左右相等
+ // 最后把前面所有的一切套进if里顺便加反转 如果为true什么都不做 如果为false直接返回false
+ if (!((left[i], right[i]) switch
+ {
+ (ImageMessage leftmsg, ImageMessage rightmsg) => !(leftmsg.ImageId != rightmsg.ImageId && leftmsg.Url != rightmsg.Url && leftmsg.Path != rightmsg.Path && leftmsg.Base64 != rightmsg.Base64),
+
+ (VoiceMessage leftmsg, VoiceMessage rightmsg) => !(leftmsg.VoiceId != rightmsg.VoiceId && leftmsg.Url != rightmsg.Url && leftmsg.Path != rightmsg.Path && leftmsg.Base64 != rightmsg.Base64),
+
+ (var leftmsg, var rightmsg) => leftmsg == rightmsg
+ })) return false;
+ }
+
+ // 如果还有代码没有直接返回false能走到这里那么估计完全相等了直接返回true
+ return true;
+ }
+
+ ///
+ /// 返回两个消息链是否不等
+ ///
+ ///
+ ///
+ ///
+ public static bool operator !=(MessageChain left, MessageChain right) => !(left == right);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool Equals(object msg)
+ {
+ return (object)this == msg;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+}
\ No newline at end of file
diff --git a/Mirai.Net/Utils/Scaffolds/MessageChainBuilder.cs b/Mirai.Net/Utils/Scaffolds/MessageChainBuilder.cs
new file mode 100644
index 0000000..fae6242
--- /dev/null
+++ b/Mirai.Net/Utils/Scaffolds/MessageChainBuilder.cs
@@ -0,0 +1,325 @@
+using Mirai.Net.Data.Messages;
+using Mirai.Net.Data.Messages.Concretes;
+using Mirai.Net.Data.Shared;
+
+namespace Mirai.Net.Utils.Scaffolds;
+
+///
+/// 消息链建造者
+///
+public class MessageChainBuilder
+{
+ private readonly MessageChain _chain = new();
+
+ ///
+ /// 清除已追加的消息
+ ///
+ ///
+ public MessageChainBuilder Clear()
+ {
+ _chain.Clear();
+ return this;
+ }
+
+ ///
+ /// 追加自定义的消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder Append(MessageBase messageBase)
+ {
+ _chain.Add(messageBase);
+ return this;
+ }
+
+ ///
+ /// 追加一条文本消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder Plain(string text)
+ {
+ _chain.Add(new PlainMessage(text));
+ return this;
+ }
+
+ ///
+ /// 追加一条at消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder At(string qq)
+ {
+ _chain.Add(new AtMessage(qq));
+ return this;
+ }
+
+ ///
+ /// 追加一条at消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder At(Member member)
+ {
+ return At(member.Id);
+ }
+
+ ///
+ /// 追加一条app消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder App(string content)
+ {
+ _chain.Add(new AppMessage
+ {
+ Content = content
+ });
+ return this;
+ }
+
+ ///
+ /// 追加一套at全体成员消息
+ ///
+ ///
+ public MessageChainBuilder AtAll()
+ {
+ _chain.Add(new AtAllMessage());
+
+ return this;
+ }
+
+ ///
+ /// 追加一条骰子消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder Dice(string value)
+ {
+ _chain.Add(new DiceMessage
+ {
+ Value = value
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加图片消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder ImageFromUrl(string url)
+ {
+ _chain.Add(new ImageMessage
+ {
+ Url = url
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加图片消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder ImageFromBase64(string base64)
+ {
+ _chain.Add(new ImageMessage
+ {
+ Base64 = base64
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加图片消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder ImageFromPath(string file)
+ {
+ _chain.Add(new ImageMessage
+ {
+ Path = file
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加图片消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder ImageFromId(string id)
+ {
+ _chain.Add(new ImageMessage
+ {
+ ImageId = id
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加图片消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder FlashImageFromUrl(string url)
+ {
+ _chain.Add(new FlashImageMessage
+ {
+ Url = url
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加闪照消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder FlashImageFromBase64(string base64)
+ {
+ _chain.Add(new FlashImageMessage
+ {
+ Base64 = base64
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加闪照消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder FlashImageFromPath(string file)
+ {
+ _chain.Add(new FlashImageMessage
+ {
+ Path = file
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加闪照消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder FlashImageFromId(string id)
+ {
+ _chain.Add(new FlashImageMessage
+ {
+ ImageId = id
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加json消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder Json(string json)
+ {
+ _chain.Add(new JsonMessage
+ {
+ Json = json
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加xml消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder Xml(string xml)
+ {
+ _chain.Add(new XmlMessage
+ {
+ Xml = xml
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加一条语音消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder VoiceFromPath(string path)
+ {
+ _chain.Add(new VoiceMessage
+ {
+ Path = path
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加一条语音消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder VoiceFromBase64(string base64)
+ {
+ _chain.Add(new VoiceMessage
+ {
+ Base64 = base64
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加一条语音消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder VoiceFromId(string id)
+ {
+ _chain.Add(new VoiceMessage
+ {
+ VoiceId = id
+ });
+
+ return this;
+ }
+
+ ///
+ /// 追加一条语音消息
+ ///
+ ///
+ ///
+ public MessageChainBuilder VoiceFromUrl(string url)
+ {
+ _chain.Add(new VoiceMessage
+ {
+ Url = url
+ });
+
+ return this;
+ }
+
+ ///
+ /// 建造消息链
+ ///
+ ///
+ public MessageChain Build()
+ {
+ return _chain;
+ }
+}
\ No newline at end of file
diff --git a/Mirai.Net/Utils/Scaffolds/MessageScaffold.cs b/Mirai.Net/Utils/Scaffolds/MessageScaffold.cs
index 9b1a96b..cd5007a 100644
--- a/Mirai.Net/Utils/Scaffolds/MessageScaffold.cs
+++ b/Mirai.Net/Utils/Scaffolds/MessageScaffold.cs
@@ -1,8 +1,9 @@
-using System.Collections.Generic;
-using System.Linq;
-using AHpx.Extensions.StringExtensions;
-using Mirai.Net.Data.Messages;
-using Mirai.Net.Data.Messages.Concretes;
+using Mirai.Net.Data.Messages;
+using Mirai.Net.Sessions.Http.Managers;
+using Mirai.Net.Utils.Internal;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
namespace Mirai.Net.Utils.Scaffolds;
@@ -11,133 +12,90 @@ namespace Mirai.Net.Utils.Scaffolds;
///
public static class MessageScaffold
{
- public static MessageBase[] Append(this string origin, params MessageBase[] append)
+ ///
+ /// 把枚举接口转换为高层MessageChain对象
+ ///
+ ///
+ ///
+ ///
+ public static MessageChain ToMessageChain(this IEnumerable source) where TSource : MessageBase
{
- var re = new List { new PlainMessage(origin) };
- re.AddRange(append);
-
- return re.ToArray();
- }
-
- public static MessageBase[] Append(this string origin, IEnumerable append)
- {
- var re = new List { new PlainMessage(origin) };
- re.AddRange(append);
-
- return re.ToArray();
- }
-
- public static MessageBase[] Append(this string origin, string append)
- {
- var re = new List { new PlainMessage(origin), new PlainMessage(append) };
-
- return re.ToArray();
- }
-
- public static MessageBase[] Append(this MessageBase messageBase, params MessageBase[] append)
- {
- var re = new List { messageBase };
- re.AddRange(append);
-
- return re.ToArray();
- }
-
- public static MessageBase[] Append(this MessageBase messageBase, IEnumerable append)
- {
- var re = new List { messageBase };
- re.AddRange(append);
-
- return re.ToArray();
+ return new MessageChain(source);
}
- public static MessageBase[] Append(this MessageBase messageBase, string append)
+ ///
+ /// 把单个消息对象转换成MessageChain对象
+ ///
+ ///
+ ///
+ ///
+ public static MessageChain ToMessageChain(this TSource origin) where TSource : MessageBase
{
- var re = new List { messageBase, new PlainMessage(append) };
-
- return re.ToArray();
+ return new MessageChain { origin };
}
- public static MessageBase[] Append(this IEnumerable bases, params MessageBase[] append)
+ ///
+ /// 转义成兼容mirai码的文本
+ ///
+ ///
+ public static string EscapeMiraiCode(this string origin)
{
- var re = bases.ToList();
- re.AddRange(append);
-
- return re.ToArray();
+ var result = origin
+ .Replace("[", @"\[")
+ .Replace("]", @"\]")
+ .Replace(":", @"\:")
+ .Replace(",", @"\,")
+ .Replace("\\", @"\\");
+
+ return result;
}
- public static MessageBase[] Append(this IEnumerable bases, string append)
- {
- var re = bases.ToList();
- re.Add(new PlainMessage(append));
-
- return re.ToArray();
- }
-
- public static MessageBase[] Append(this IEnumerable bases, IEnumerable append)
+ ///
+ /// 在指定的时间之后撤回消息
+ ///
+ ///
+ /// 好友id或群id
+ ///
+ public static async Task RecallAfter(this Task messageIdTask, string target, TimeSpan duration)
{
- var re = bases.ToList();
- re.AddRange(append);
-
- return re.ToArray();
+ var messageId = await messageIdTask;
+ DispatchUtils.ExecuteScheduledActionAsync(duration, async () =>
+ {
+ await MessageManager.RecallAsync(messageId, target);
+ });
}
- public static bool Contains(this IEnumerable bases, string message)
+ ///
+ /// 在指定的时间之后撤回消息
+ ///
+ ///
+ /// 好友id或群id
+ ///
+ public static async Task RecallAfter(this Task messageIdTask, string target, int milliseconds)
{
- return bases.Select(x => x.ToJsonString()).Any(x => x.Contains(message));
+ await messageIdTask.RecallAfter(target, TimeSpan.FromMilliseconds(milliseconds));
}
-
- public static bool Contains(this IEnumerable bases, string message, out MessageBase messageBase)
- {
- foreach (var @base in bases)
- {
- var json = @base.ToJsonString();
- if (json.Contains(message))
- {
- messageBase = @base;
- return true;
- }
- }
- messageBase = null;
- return false;
- }
-
- public static bool Contains(this IEnumerable bases, string message, out IEnumerable origin)
+ ///
+ /// 在指定时间之后发送消息,这是个同步方法
+ ///
+ ///
+ ///
+ public static void SendAfter(this Task messageTask, TimeSpan duration)
{
- var messageBases = bases.ToList();
- foreach (var @base in messageBases)
+ DispatchUtils.ExecuteScheduledActionAsync(duration, async () =>
{
- var json = @base.ToJsonString();
- if (json.Contains(message))
- {
- origin = messageBases;
- return true;
- }
- }
-
- origin = null;
- return false;
+ await messageTask;
+ });
}
- public static string GetPlainMessage(this IEnumerable messageChain)
- {
- var messageBases = messageChain.ToList();
- if (messageBases.OfType().Any())
- {
- return messageBases
- .OfType()
- .Select(x => x.Text)
- .Aggregate((s, s1) => s + s1)
- .Trim();
- }
-
- return null;
- }
-
- public static IEnumerable GetSeparatedPlainMessage(this IEnumerable messageChain)
+ ///
+ /// 在指定时间之后发送消息,这是个同步方法
+ ///
+ ///
+ ///
+ public static void SendAfter(this Task messageTask, int milliseconds)
{
- return messageChain
- .OfType()
- .Select(x => x.Text);
+ messageTask.SendAfter(TimeSpan.FromMilliseconds(milliseconds));
}
}
\ No newline at end of file
diff --git a/Mirai.Net/Utils/Scaffolds/MiraiScaffold.cs b/Mirai.Net/Utils/Scaffolds/MiraiScaffold.cs
index 996dc6e..a51c82d 100644
--- a/Mirai.Net/Utils/Scaffolds/MiraiScaffold.cs
+++ b/Mirai.Net/Utils/Scaffolds/MiraiScaffold.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using AHpx.Extensions.JsonExtensions;
+using Manganese.Text;
using Mirai.Net.Data.Events.Concretes.Request;
using Mirai.Net.Data.Messages;
using Mirai.Net.Data.Messages.Concretes;
@@ -12,9 +9,17 @@
using Mirai.Net.Sessions;
using Mirai.Net.Sessions.Http.Managers;
using Mirai.Net.Utils.Internal;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Linq;
+using System.Threading.Tasks;
namespace Mirai.Net.Utils.Scaffolds;
+///
+/// mirai相关拓展方法
+///
public static class MiraiScaffold
{
#region MiraiBot extensions
@@ -72,54 +77,54 @@ public static bool IsFriend(this MiraiBot bot, Friend friend)
return bot.Friends.Value.Any(x => x.Id == friend.Id);
}
- #endregion
-
- #region Legacy command module extensions
-
///
- /// 执行命令模块
+ /// An encapsulation of 'OfType.Subscribe' for GroupMessageReceiver
///
///
- ///
+ ///
///
- [Obsolete]
- public static IObservable WithCommandModules(this IObservable observable,
- params ICommandModule[] modules)
+ public static IDisposable SubscribeGroupMessage(this IObservable observable, Action action)
{
- observable.Subscribe(x => { x.ExecuteCommandModules(modules); });
-
- return observable;
+ return observable.OfType().Subscribe(action);
}
///
- /// 执行指定类型同命名空间下所有命令模块(除非它没开启)
+ /// An encapsulation of 'OfType.Subscribe' for GroupMessageReceiver
///
///
+ ///
///
- [Obsolete]
- public static IObservable WithCommandModules(
- this IObservable observable) where T : ICommandModule
+ public static IDisposable SubscribeGroupMessageAsync(this IObservable observable, Func action)
{
- var particular = CommandScaffold.LoadCommandModules();
- observable.Subscribe(x => { x.ExecuteCommandModules(particular); });
-
- return observable;
+ return observable.OfType().Subscribe(r =>
+ {
+ action(r);
+ });
}
///
- /// 执行指定命名空间下所有命令模块(除非它没开启)
+ /// An encapsulation of 'OfType.Subscribe' for FriendMessageReceiver
///
///
- ///
+ ///
///
- [Obsolete]
- public static IObservable WithCommandModules(this IObservable observable,
- string @namespace)
+ public static IDisposable SubscribeFriendMessage(this IObservable observable, Action action)
{
- var particular = CommandScaffold.LoadCommandModules(@namespace);
- observable.Subscribe(x => { x.ExecuteCommandModules(particular); });
+ return observable.OfType().Subscribe(action);
+ }
- return observable;
+ ///
+ /// An encapsulation of 'OfType.Subscribe' for GroupMessageReceiver
+ ///
+ ///
+ ///
+ ///
+ public static IDisposable SubscribeFriendMessageAsync(this IObservable observable, Func action)
+ {
+ return observable.OfType().Subscribe(r =>
+ {
+ action(r);
+ });
}
#endregion
@@ -137,6 +142,18 @@ public static T Concretize(this MessageReceiverBase @base) where T : MessageR
return (T)@base;
}
+ ///
+ /// 使用模块
+ ///
+ ///
+ ///
+ ///
+ public static IObservable WithModules(this IObservable source, List modules)
+ {
+ source.Subscribe(modules.Raise);
+ return source;
+ }
+
#endregion
#region Message extension
@@ -148,7 +165,7 @@ public static T Concretize(this MessageReceiverBase @base) where T : MessageR
///
///
public static async Task SendMessageAsync(this GroupMessageReceiver receiver,
- params MessageBase[] chain)
+ MessageChain chain)
{
return await MessageManager
.SendGroupMessageAsync(receiver.Sender.Group.Id, chain);
@@ -161,7 +178,7 @@ public static async Task SendMessageAsync(this GroupMessageReceiver rece
///
///
public static async Task SendMessageAsync(this FriendMessageReceiver receiver,
- params MessageBase[] chain)
+ MessageChain chain)
{
return await MessageManager
.SendFriendMessageAsync(receiver.Sender.Id, chain);
@@ -173,61 +190,53 @@ public static async Task SendMessageAsync(this FriendMessageReceiver rec
///
///
///
- public static async Task SendMessageAsync(this TempMessageReceiver receiver, params MessageBase[] chain)
+ public static async Task SendMessageAsync(this TempMessageReceiver receiver, MessageChain chain)
{
return await MessageManager
.SendTempMessageAsync(receiver.Sender.Id, receiver.Sender.Group.Id, chain);
}
///
- /// 发送群消息
- ///
- ///
- ///
- ///
- public static async Task SendMessageAsync(this GroupMessageReceiver receiver, string message)
- {
- return await MessageManager
- .SendGroupMessageAsync(receiver.Sender.Group.Id, message);
- }
-
- ///
- /// 发送好友消息
+ /// 撤回收到的消息
///
///
- ///
- ///
- public static async Task SendMessageAsync(this FriendMessageReceiver receiver, string message)
+ public static async Task RecallAsync(this GroupMessageReceiver receiver)
{
- return await MessageManager
- .SendFriendMessageAsync(receiver.Sender.Id, message);
+ var id = receiver.MessageChain.OfType().First().MessageId;
+ await MessageManager
+ .RecallAsync(id, receiver.GroupId);
}
///
- /// 发送临时消息
+ /// 撤回收到的消息
///
///
- ///
- ///
- public static async Task SendMessageAsync(this TempMessageReceiver receiver, string message)
+ public static async Task RecallAsync(this FriendMessageReceiver receiver)
{
- return await MessageManager
- .SendTempMessageAsync(receiver.Sender.Id, receiver.Sender.Group.Id, message);
+ var id = receiver.MessageChain.OfType().First().MessageId;
+ await MessageManager
+ .RecallAsync(id, receiver.FriendId);
}
///
/// 撤回收到的消息
///
///
- public static async Task RecallAsync(this MessageReceiverBase receiver)
+ public static async Task RecallAsync(this TempMessageReceiver receiver)
{
var id = receiver.MessageChain.OfType().First().MessageId;
await MessageManager
- .RecallAsync(id);
+ .RecallAsync(id, receiver.Sender.Id);
}
+ ///
+ /// 回复消息
+ ///
+ ///
+ ///
+ ///
public static async Task QuoteMessageAsync(this FriendMessageReceiver receiver,
- params MessageBase[] chain)
+ MessageChain chain)
{
var id = receiver.MessageChain.OfType().First().MessageId;
@@ -235,8 +244,14 @@ public static async Task QuoteMessageAsync(this FriendMessageReceiver re
.QuoteFriendMessageAsync(receiver.Sender.Id, id, chain);
}
+ ///
+ /// 回复消息
+ ///
+ ///
+ ///
+ ///
public static async Task QuoteMessageAsync(this GroupMessageReceiver receiver,
- params MessageBase[] chain)
+ MessageChain chain)
{
var id = receiver.MessageChain.OfType().First().MessageId;
@@ -244,8 +259,14 @@ public static async Task QuoteMessageAsync(this GroupMessageReceiver rec
.QuoteGroupMessageAsync(receiver.Sender.Group.Id, id, chain);
}
+ ///
+ /// 回复消息
+ ///
+ ///
+ ///
+ ///
public static async Task QuoteMessageAsync(this TempMessageReceiver receiver,
- params MessageBase[] chain)
+ MessageChain chain)
{
var id = receiver.MessageChain.OfType().First().MessageId;
@@ -253,30 +274,6 @@ public static async Task QuoteMessageAsync(this TempMessageReceiver rece
.QuoteTempMessageAsync(receiver.Sender.Id, receiver.Sender.Group.Id, id, chain);
}
- public static async Task QuoteMessageAsync(this FriendMessageReceiver receiver, string message)
- {
- var id = receiver.MessageChain.OfType().First().MessageId;
-
- return await MessageManager
- .QuoteFriendMessageAsync(receiver.Sender.Id, id, message);
- }
-
- public static async Task QuoteMessageAsync(this GroupMessageReceiver receiver, string message)
- {
- var id = receiver.MessageChain.ToList().OfType().First().MessageId;
-
- return await MessageManager
- .QuoteGroupMessageAsync(receiver.Sender.Group.Id, id, message);
- }
-
- public static async Task QuoteMessageAsync(this TempMessageReceiver receiver, string message)
- {
- var id = receiver.MessageChain.OfType().First().MessageId;
-
- return await MessageManager
- .QuoteTempMessageAsync(receiver.Sender.Id, receiver.Sender.Group.Id, id, message);
- }
-
#endregion
#region Request extensions
@@ -287,18 +284,49 @@ public static async Task QuoteMessageAsync(this TempMessageReceiver rece
///
///
///
+ [Obsolete("请使用直接Approve/RejectAndBlock/RejectAsync 等方法")]
public static async Task Handle(this NewFriendRequestedEvent @event,
NewFriendRequestHandlers handler, string message = "")
{
await RequestManager.HandleNewFriendRequestedAsync(@event, handler, message);
}
+ ///
+ /// 同意好友请求
+ ///
+ ///
+ public static async Task ApproveAsync(this NewFriendRequestedEvent @event)
+ {
+ await RequestManager.HandleNewFriendRequestedAsync(@event, NewFriendRequestHandlers.Approve);
+ }
+
+ ///
+ /// 拒绝好友请求
+ ///
+ /// 事件
+ /// 回复的消息
+ public static async Task RejectAsync(this NewFriendRequestedEvent @event, string message = "")
+ {
+ await RequestManager.HandleNewFriendRequestedAsync(@event, NewFriendRequestHandlers.Reject, message);
+ }
+
+ ///
+ /// 拒绝好友请求且屏蔽对方
+ ///
+ /// 事件
+ /// 回复的消息
+ public static async Task RejectAndBlockAsync(this NewFriendRequestedEvent @event, string message = "")
+ {
+ await RequestManager.HandleNewFriendRequestedAsync(@event, NewFriendRequestHandlers.RejectAndBlock, message);
+ }
+
///
/// 处理新成员加群请求
///
///
///
///
+ [Obsolete("请使用直接Approve/RejectAndBlock/RejectAsync 等方法")]
public static async Task Handle(this NewMemberRequestedEvent requestedEvent,
NewMemberRequestHandlers handler, string message = "")
{
@@ -306,18 +334,86 @@ await RequestManager
.HandleNewMemberRequestedAsync(requestedEvent, handler, message);
}
+ ///
+ /// 同意加群请求
+ ///
+ ///
+ public static async Task ApproveAsync(this NewMemberRequestedEvent requestedEvent)
+ {
+ await RequestManager.HandleNewMemberRequestedAsync(requestedEvent, NewMemberRequestHandlers.Approve);
+ }
+
+ ///
+ /// 拒绝加群请求
+ ///
+ /// 事件源
+ /// 回复消息
+ public static async Task RejectAsync(this NewMemberRequestedEvent requestedEvent, string message = "")
+ {
+ await RequestManager.HandleNewMemberRequestedAsync(requestedEvent, NewMemberRequestHandlers.Reject, message);
+ }
+
+ ///
+ /// 忽略加群请求
+ ///
+ ///
+ public static async Task DismissAsync(this NewMemberRequestedEvent requestedEvent)
+ {
+ await RequestManager.HandleNewMemberRequestedAsync(requestedEvent, NewMemberRequestHandlers.Dismiss);
+ }
+
+ ///
+ /// 拒绝加群请求并屏蔽
+ ///
+ ///
+ /// 回复消息
+ public static async Task RejectAndBlockAsync(this NewMemberRequestedEvent requestedEvent, string message = "")
+ {
+ await RequestManager.HandleNewMemberRequestedAsync(requestedEvent, NewMemberRequestHandlers.RejectAndBlock, message);
+ }
+
+ ///
+ /// 忽略加群请求并屏蔽
+ ///
+ ///
+ public static async Task DismissAndBlockAsync(this NewMemberRequestedEvent requestedEvent)
+ {
+ await RequestManager.HandleNewMemberRequestedAsync(requestedEvent, NewMemberRequestHandlers.DismissAndBlock);
+ }
+
///
/// 处理bot被邀请进群请求
///
///
///
///
- public static async Task Handle(NewInvitationRequestedEvent requestedEvent,
+ [Obsolete("请使用直接Approve/RejectAndBlock/RejectAsync 等方法")]
+ public static async Task Handle(this NewInvitationRequestedEvent requestedEvent,
NewInvitationRequestHandlers handler, string message)
{
await RequestManager
.HandleNewInvitationRequestedAsync(requestedEvent, handler, message);
}
+ ///
+ /// 同意邀请
+ ///
+ ///
+ public static async Task ApproveAsync(this NewInvitationRequestedEvent requestedEvent)
+ {
+ await RequestManager.HandleNewInvitationRequestedAsync(requestedEvent, NewInvitationRequestHandlers.Approve,
+ "");
+ }
+
+ ///
+ /// 拒绝邀请
+ ///
+ ///
+ public static async Task RejectAsync(this NewInvitationRequestedEvent requestedEvent)
+ {
+ await RequestManager.HandleNewInvitationRequestedAsync(requestedEvent, NewInvitationRequestHandlers.Reject,
+ "");
+ }
+
#endregion
}
\ No newline at end of file
diff --git a/Mirai.Net/Utils/Scaffolds/ModuleScaffold.cs b/Mirai.Net/Utils/Scaffolds/ModuleScaffold.cs
index 0aee09b..a4beecc 100644
--- a/Mirai.Net/Utils/Scaffolds/ModuleScaffold.cs
+++ b/Mirai.Net/Utils/Scaffolds/ModuleScaffold.cs
@@ -1,30 +1,32 @@
-using System;
+using Mirai.Net.Data.Messages;
+using Mirai.Net.Modules;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
-using Mirai.Net.Data.Messages;
-using Mirai.Net.Modules;
namespace Mirai.Net.Utils.Scaffolds;
+///
+/// 模块化拓展方法
+///
public static class ModuleScaffold
{
///
/// 获取泛型参数同一个命名空间下的所有模块
///
///
- public static IEnumerable GetModules(this T module)
+ public static List GetModules(this T module) where T : IModule
{
var basic = typeof(T);
-
+
var types = Assembly.GetAssembly(basic).GetTypes()
.Where(x => x.IsClass && !x.IsAbstract && !x.IsInterface)
.Where(x => x.GetInterfaces().Any(x => x == typeof(IModule)))
.Where(x => x!.FullName!.Contains(basic.Namespace!))
.ToList();
- foreach (var type in types)
- yield return Activator.CreateInstance(type) as IModule;
+ return types.Select(t => Activator.CreateInstance(t) as IModule).ToList();
}
///
@@ -32,7 +34,7 @@ public static IEnumerable GetModules(this T module)
///
///
///
- public static void SubscribeModule(this IEnumerable modules, MessageReceiverBase @base)
+ public static void Raise(this List modules, MessageReceiverBase @base)
{
foreach (var module in modules)
{
diff --git a/README.md b/README.md
index f3ada6c..a05de9c 100644
--- a/README.md
+++ b/README.md
@@ -1,112 +1,41 @@
-# Mirai.Net 2.4.0-Pre1
+# Mirai.Net 2.5.2
-Mirai.Net 是基于[mirai-api-http]实现的轻量级[mirai]社区 sdk。 此项目遵循
-[AGPL-3.0 LICENSE](https://github.com/AHpxChina/Mirai.Net/blob/master/LICENSE)
-开源。
+Mirai.NET 是基于 [mirai-api-http] 实现的 C# 版轻量级 [mirai] 社区 SDK。
-本项目的 QQ 群: `1042821169`,需要技术支持或者有什么问题(甚至水群聊天),欢迎加入群聊探讨。
+此项目遵循 [AGPL-3.0](https://github.com/AHpxChina/Mirai.Net/blob/master/LICENSE) 协议开源。
-项目文档: https://sinoahpx.github.io/Mirai.Net.Documents
+QQ 群: [752379554](https://jq.qq.com/?_wv=1027&k=gdWqppEO)欢迎加入群聊探讨 ~~以及水群聊天~~
-如果你觉得这是个很酷的项目的话,不妨考虑给它点一个Star,如果你还觉得挺酷但还不够好的话,也欢迎提交Pull Request和Issue。
+文档:[Mirai.Net Documents](https://sinoahpx.github.io/Mirai.Net.Documents)
+
+如果你这个项目还不错,不妨考虑给它点一个 Star。
+
+如果你还觉得挺酷但还不够好的话,也欢迎提交 Pull Request 和 Issue。
## 速览
- 基于 [.NET Standard 2.0](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) 开发,支持跨平台。
-- 适配最新的[mirai-api-http]插件。
-- 实现了[mirai-api-http]的`Http Adapter`和`Websocket Adapter`
- - `Http Adapter`用来进行发送操作。
- - `Websocket Adapter`用来进行接收操作。
+- 适配最新的 [mirai-api-http] 插件。
+- 实现了 [mirai-api-http] 的 `Http Adapter` 和 `Websocket Adapter`
+ - `Http Adapter` 用来进行发送操作。
+ - `Websocket Adapter` 用来进行接收操作。
- 基于 [Rx.NET](https://github.com/dotnet/reactive) 的推送系统。
- 有一堆好用的脚手架和拓展方法。
- 提供了简单的模块化和命令系统实现。
- 源代码结构
- Mirai.Net,主项目
- Mirai.Net.Test,控制台测试项目
- - Mirai.Net.UnitTest,单元测试项目(现在没啥用了)
-
-
- 实现的接口列表
-
-_斜体的标注的接口是不稳定的_
-
-~~删除线标注的接口是未实现的~~
-
-- 账号信息
- - 获取好友列表
- - 获取群列表
- - 获取群成员列表
- - 获取 Bot 资料
- - 获取好友资料
- - 获取群成员资料
-- 消息发送和撤回
- - 发送好友消息
- - 发送群消息
- - 发送临时会话消息
- - 发送头像戳一戳消息
- - 撤回消息
-- 文件操作
- - _查看文件列表_
- - _获取文件信息_
- - _创建文件夹_
- - ~~删除文件~~
- - ~~移动文件~~
- - ~~重命名文件~~
-- 多媒体内容上传
- - 图片文件上传
- - 语音文件上传
- - 群文件上传
-- 账号管理
- - 删除好友
-- 群管理
- - 禁言群成员
- - 解除群成员禁言
- - 移除群成员
- - 退出群聊
- - 全体禁言
- - 解除全体禁言
- - 设置群精华消息
- - 获取群设置
- - 修改群设置
- - 获取群员设置
- - 修改群员设置
-- 事件处理
- - 添加好友申请
- - 用户入群申请
- - Bot 被邀请入群申请
-
-
-
-
- 支持的消息类型
-
-- Quote - 回复消息
-- At - @消息
-- AtAll - @全体成员
-- Face - QQ 表情
-- Plain - 纯文本
-- Image - 图片
-- FlashImage - 闪照
-- Voice - 语音
-- Xml - XML 消息
-- Json - JSON 消息
-- App - App 消息
-- Poke - 戳一戳
-- Dice - 不知道是啥玩意
-- MusicShare - 音乐分享
-- ForwardMessage - 转发消息
-- File - 文件
-
+ - Mirai.Net.UnitTest,单元测试项目(现在没啥用了)
## 快速上手
-**(以下仅为一些简单示例,如果需要更详细的说明,请移步[文档]。有时候文档跟不上版本请[进群提问](#Mirai.Net 2.4.0-Pre1))**
+**(以下仅为一些简单示例,如果需要更详细的说明,请移步[文档]。有时候文档跟不上版本请[进群提问](#mirainet-239)**
### 安装
- 使用 Nuget 安装(推荐)
- - Nuget 包管理器: `Install-Package Mirai.Net -Version 2.4.0-Pre1`
- - .NET CLI: `dotnet add package Mirai.Net --version 2.4.0-Pre1`
+ - Nuget 包管理器: `Install-Package Mirai.Net`
+ - .NET CLI: `dotnet add package Mirai.Net`
- **或者在 IDE 的可视化界面搜索`Mirai.Net`安装最新版。**
- 自己克隆这个仓库的默认分支,然后自己编译,然后自己添加 dll 引用。
@@ -132,7 +61,7 @@ using Mirai.Net.Sessions;
using var bot = new MiraiBot
{
Address = "localhost:8080",
- QQ = xx,
+ QQ = "xx",
VerifyKey = "xx"
};
```
@@ -175,20 +104,20 @@ bot.EventReceived
发送消息的方法有两个参数: 发送到哪里和发送什么。所以第一个参数就是发消息的群号,第二个参数就是要发送的消息链(或者字符串)。
```cs
-await manager.SendGroupMessageAsync("xx", "Hello, World");
+await MessageManager.SendGroupMessageAsync("xx", "Hello, World");
```
或者:
```cs
-await manager.SendGroupMessageAsync("xx", "Hello, ".Append(new AtMessage("xx")).Append(" !"));
+await MessageManager.SendGroupMessageAsync("xx", new MessageChainBuilder().Plain("Hello, ").At("xx").Build());
```
## 贡献
-此项目欢迎任何人的[Pull Request](https://github.com/AHpxChina/Mirai.Net/pulls) 和[Issue](https://github.com/AHpxChina/Mirai.Net/issues),也欢迎 Star 和 Fork。
+此项目欢迎任何人的 [Pull Request](https://github.com/AHpxChina/Mirai.Net/pulls) 和 [Issue](https://github.com/AHpxChina/Mirai.Net/issues) 也欢迎 Star 和 Fork。
-如果你认为文档不够好,也欢迎对[文档仓库](https://github.com/SinoAHpx/Mirai.Net.Documents)提交[Pull Request](https://github.com/AHpxChina/Mirai.Net.Documents/pulls)和[Issue](https://github.com/AHpxChina/Mirai.Net.Documents/issues)
+如果你认为文档不够好,也欢迎对 [文档仓库](https://github.com/SinoAHpx/Mirai.Net.Documents) 提交 [Pull Request](https://github.com/AHpxChina/Mirai.Net.Documents/pulls) 和 [Issue](https://github.com/AHpxChina/Mirai.Net.Documents/issues)。
## 致谢
@@ -199,7 +128,7 @@ await manager.SendGroupMessageAsync("xx", "Hello, ".Append(new AtMessage("xx")).
- [Json.NET](http://json.net/) ~~这甚至是这个项目名称的灵感来源~~
- [Websocket.Client](https://github.com/Marfusios/websocket-client)
- [Rx.NET](https://github.com/dotnet/reactive)
-- [AHpx.Extensions](https://github.com/AHpxChina/AHpx.E*xtensions)
+- [Manganese](https://github.com/SinoAHpx/Manganese)
[mirai-api-http]: https://github.com/project-mirai/mirai-api-http
[mirai]: https://github.com/mamoe/mirai