Open Pinkuburu opened 4 weeks ago
感谢提问。 在使用ServiceFactory创建服务后,会返回IWebSocketService接口,接口中有Contexts属性,表示当前有效的上下文。 https://github.com/XeronOwO/Makabaka/blob/main/Makabaka%2FServices%2FIWebSocketService.cs#L43-L43 当存在有效的上下文时,可以通过调用上下文进行主动的消息操作,比如SendPrivateMessageAsync。
意思要有上下文的聊天内容文字,才能触发主动的消息发送? 但是我和某用户就没有聊天记录呢?例如我A定时给B发送一个消息 不好意思我可能显得过于愚笨,如果可以,我想看一下代码示例,感谢您 如有打扰,抱歉
大致的运行逻辑如下:
https://github.com/XeronOwO/Makabaka/blob/main/Makabaka/Services/ServiceFactory.cs#L17 通过ServiceFactory创建并返回IWebSocketService接口。这个接口负责启动、停止整体的服务。
https://github.com/XeronOwO/Makabaka/blob/main/Makabaka/Services/ForwardWebSocketService.cs#L58 当启动服务后,会创建对应的IWebSocketContext,保存到Contexts属性中,该IWebSocketContext负责处理Lagrange.Core的网络连接。
也就是说,这个“上下文”指的是WebSocket这个连接,而不是指具体跟某个用户的聊天记录。
所以IWebSocketService的Contexts其实就是WebSocket连接,直接调用其接口功能就行了。我也不记得当初为什么要用List来存,感觉用nullable就行了。
这样解释好理解不
那大概理解了 所以我把service 变量设为全局变量 然后我在需要的地方await service.Contexts[0].SendPrivateMessageAsync(123456789, new TextSegment("测试!"));
但你的这个SDK设计的方法是在service正式启动前,把需要监听的事件绑定上去,诸如OnPrivateMessage、OnGroupMessage
但我SendPrivateMessageAsync不经事件触发,或者说场景更极端点,机器人A和用户B,从来不聊天,只有A主动给B发消息 那就无法在程序一开始通过绑定一系列事件去允许触发SendPrivateMessageAsync service.OnGroupMessage += OnGroupMessage; service.OnPrivateMessage += OnPrivateMessage;
例如我30分钟执行一次 Notice(){ await service.Contexts[0].SendPrivateMessageAsync(123456789, new TextSegment("测试!")); }
SendPrivateMessageAsync的本质就是向Lagrange.Core发送WebSocket数据。即 Makabaka --SendPacket --> Lagrange.Core 。 而OnPrivateMessage,是在接收到Lagrange.Core发来的数据并解析后,再调用,类似于C/C++的回调函数。即 Lagrange.Core --SendPacket --> Makabaka 。 这两个没有谁先谁后的要求。在成功连接上Lagrange.Core后,就可以使用SendPrivateMessageAsync发送消息,不需要OnPrivateMessage事件。
🫣那有可能是我的框架问题,其实我用的是napcat的那个…我下午试试改下代码看看,现在如果在非事件中的地方运行那句代码,就断开了ws链接…🫣🫣🫣应该是我太菜了哪里写错了
Program.cs
private const string ConfigPath = "config.json";
public static IWebSocketService service;
static async Task Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.Console()
.CreateLogger(); // 配置日志
// 加载配置
ForwardWebSocketServiceConfig? config = null;
if (File.Exists(ConfigPath))
{
config = JsonConvert.DeserializeObject<ForwardWebSocketServiceConfig>(File.ReadAllText(ConfigPath));
}
config ??= new();
File.WriteAllText(ConfigPath, JsonConvert.SerializeObject(config, Formatting.Indented));
// 初始化服务
service = ServiceFactory.CreateForwardWebSocketService(config);
service.OnGroupMessage += OnGroupMessage;
service.OnPrivateMessage += OnPrivateMessage;
service.OnGroupRequest += OnGroupRequest;
service.OnAddFriendRequest += OnFriendRequest;
//service.OnGroupFileUpload += OnGroupFileUpload;
// 启动服务
var cts = new CancellationTokenSource();
AssemblyLoadContext.Default.Unloading += ctx => cts.Cancel();
Console.CancelKeyPress += (sender, eventArgs) => cts.Cancel();
await service.StartAsync();
await WatchRunner.UpdateAllPlayersEveryXMinutes(0.1);
// 等待取消信号
try
{
await Task.Delay(Timeout.Infinite, cts.Token);
}
catch (TaskCanceledException)
{
// 服务停止
}
await service.StopAsync();
}
WatchRunner.cs
namespace Makabaka.Test.app.Dota2Bot
{
internal static class WatchRunner
{
/// <summary>
/// 定时更新所有在playerHelper数据库中的玩家的比赛信息
/// 并将战报发送出去
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
static public async Task UpdateAllPlayersEveryXMinutes(double x)
{
while (true)
{
//如果改为true,就是报喜不报忧
if (true)
{
Console.WriteLine("UpdateAllPlayersEveryXMinutes");
await Program.service.Contexts[0].SendGroupMessageAsync(100399266, new TextSegment("回复测试!"));
}
Thread.Sleep(TimeSpan.FromMinutes(x));
}
}
}
}
控制台输出
[21:03:07 INF] 正在启动正向WebSocket服务 [21:03:07 INF] 创建正向WebSocket[6a82e1fa-b8bd-45fc-b44c-d32caee71474] [21:03:07 INF] [6a82e1fa-b8bd-45fc-b44c-d32caee71474]尝试连接ws://192.168.50.162:43001/ UpdateAllPlayersEveryXMinutes [21:03:07 DBG] [6a82e1fa-b8bd-45fc-b44c-d32caee71474]发送数据:{"params":{"group_id":100399266,"message":[{"type":"text","data":{"text":"回复测试!"}}],"auto_escape":false},"action":"send_group_msg","echo":"4f39852f-424a-4fe5-be61-6956336c7ed5"} [21:03:07 INF] [6a82e1fa-b8bd-45fc-b44c-d32caee71474]断开连接
实在不好意思,学习的水平有限,劳请指教一下……谢谢
这个的问题是操作太快了,这还没连接上就发送数据了。
而且连接上之后,需要握手鉴权,如果没有鉴权或者鉴权失败,是会直接断开连接的。
可以用下OnLifeCycle
事件,具体的EventArgs
可以参考 Onebot生命周期 。
搞定了,应该是可以了 我没想到OnLifeCycle这个东西……我继续去研究下
`[02:26:58 DBG] [de432cc7-d0fc-499f-a8e2-e86bad873228]接收数据:{"time":1726252018,"self_id":999999999,"post_type":"notice","notice_type":"notify","sub_type":"input_status","status_text":"对方正在输入...","event_type":1,"user_id":1012803704,"group_id":0}
[02:26:58 ERR] [de432cc7-d0fc-499f-a8e2-e86bad873228]处理数据时出现异常 System.Exception: 不支持的notice_type:notify at Makabaka.Utils.DataProcessor.ProcessNotice(String data, JObject json) in D:\ProgramRepos\Makabaka-main\Makabaka\Utils\DataProcessor.cs:line 217 at Makabaka.Utils.DataProcessor.ProcessPost(String data, JObject json) in D:\ProgramRepos\Makabaka-main\Makabaka\Utils\DataProcessor.cs:line 91 at Makabaka.Utils.DataProcessor.Process(String data) in D:\ProgramRepos\Makabaka-main\Makabaka\Utils\DataProcessor.cs:line 73 at Makabaka.Network.ForwardWebSocketContext.MessageReceived(Object sender, MessageReceivedEventArgs e) in D:\ProgramRepos\Makabaka-main\Makabaka\Network\ForwardWebSocketContext.cs:line 97 `
我拿手机给机器人打消息(还没发出去的时候)就会发生报错(不影响程序),你看是不是要修
这个看样子是“正在输入”的数据包,我还没写解析,不过不影响运行。感觉这个数据包一般也用不上吧,要支持解析倒也不难,DataProcessor里面添加处理函数就行。主要是最近比较忙,也没啥时间维护项目了
代码示例中的发送消息,都是收到消息再发送回复,根据EventArgs的内容来获取相关信息 但是请问想要主动给某人发送消息,怎么实现SendPrivateMessage