.net 6 [ver 6.0.x]
@{
所.有.用.户.必.须.更.新.至.最.新.版.本
ver 6.0.0 删除了关于Linux对于System.Drawing.Common的引用;
由于微软不再支持libgdi+,故删除
ver 6.0.1 修改了一处序列化错误
改动说明:
maj 1.修复了信息内容的更新操作
maj 2.增加了戳回去 e.NudgeBack(Client)函数
maj 3.优化了标准处理流,增加了WatchDog守护链
maj 4.MGetEachImageImage()扩展删除
min 1.修改了序列化操作的代码
min 2.增加了信息类.SendTo__(target,client)方法
}
//这是一个最简.net6版本顶级语句 [仅对于高级开发人员使用]
MeowMiraiLib.Client c = new("ws://ip:port/all?verifyKey=...&qq=...", true, true, -1);
c.Connect();
//c.ConnectAsync()
c.OnFriendMessageReceive += (s, e) => { };
//c.事件 += (s,e) => { 处理函数 }
while (true)
{
switch (System.Console.ReadLine()) // 控制台操作
{
//.....
}
}
MeowMiraiLib.Client c = new("ws://test.com.cn:8888/all?verifyKey=123456&qq=1234567", true, true);
MeowMiraiLib.Client c2 = new("test.com.cn", 8888, "123456", 1234567, "all", true, true);
方案为, 在顶级语句外进行实例化
, 在顶级语句内引用.
例如在ClientX.cs文件内,实例化所有您需要使用的端.
您可以使用同时使用多个端
, 或者重复链接
一个端, 他们会自动组织
Session和其他问题.
注:本教程后续的发送端均调用在这个类
//文件ClientX.cs
namespace Test
{
public static class ClientX
{
//换成自己要用的参数
public static MeowMiraiLib.Client c = new("ws://test.com.cn:8888/all?verifyKey=123456&qq=1234567", true, true);
public static MeowMiraiLib.Client c2 = new("test.com.cn", 8888, "123456", 1234567, "all", true, true);
}
}
顶级语句则变成如下写法:
using System;
using Test; //项目名
using static Test.ClientX;
c.Connect();
c.OnFriendMessageReceive += MessageX.OnFriendMessageReceive;
//c.事件 += (s,e) => { 处理函数 }
while (true)
{
switch (Console.ReadLine()) // 控制台操作
{
//.....
}
}
ps.为了保持顶级语句的整洁, 当发送信息时, 我们建议您应当另开新文件, 创建新静态类处理, 使用事件注册来控制.
ps2.
本框架调用段完全收发自由, 您无需先收后发,
您可以直接
进行发送信息
, 也可以接受到信息后不产生回应
,
比如整点报时, 不需要收到信息然后产生动作.
当然,在本例中我们使用MessageX.cs文件中的MessageX类来处理客户端接受的信息.
您可以 自定义 类的名称.
//MessageX类
using MeowMiraiLib.Msg.Sender;
using MeowMiraiLib.Msg.Type;
namespace Test
{
internal class MessageX
{
public static void OnFriendMessageReceive(FriendMessageSender s, Message[] e)
{
System.Console.WriteLine($"好友信息 [qq:{s.id},昵称:{s.nickname},备注:{s.remark}] \n内容:{e.MGetPlainString()}");
//MGetPlainString() 是一个关于Message类的数组扩展方法,用于返回信息里的文字部分
//....其他操作
}
}
}
在顶级语句内添加如下字段
//顶级语句...
c.OnFriendMessageReceive += MeowMiraiLibTest.MessageX.OnFriendMessageReceive;
//...
运行,并尝试发送给您的机器人一段文字.
~至此,接收端就这样做成了.
在本节中,我们主要讨论 收到信息后的发送
和 主动发送信息
假设我们从
好友信息
中读取数据.
1.首先需要先规定命令的格式 例如: 重复 [要重复的内容]
2.写一个处理这个事件的函数, 传入数据为原始信息需要的部分, 输出为一个Message[]数组等待发送.
3.发送这个信息,使用某个端发送.
原始写法
using MeowMiraiLib.Msg;
using MeowMiraiLib.Msg.Sender;
using MeowMiraiLib.Msg.Type;
namespace Test
{
internal class MessageX
{
public static void OnFriendMessageReceive(FriendMessageSender s, Message[] e)
{
//MGetPlainStringSplit() 是一个关于Message类的数组扩展方法,
//用于返回信息里的文字部分后按照 Splitor进行分割, splitor默认是空格
var sx = e.MGetPlainStringSplit();
var sendto = s.id;
var msg = sx[0] switch
{
"重复" => Repeat(sx[1]),
_ => null,
};
new FriendMessage(sendto, msg).Send(ClientX.c);
}
//重复消息
public static Message[] Repeat(string s) => new Message[] { new Plain(s) };
}
}
扩展写法
using MeowMiraiLib.Msg;
using MeowMiraiLib.Msg.Sender;
using MeowMiraiLib.Msg.Type;
namespace Test
{
internal class MessageX
{
public static void OnFriendMessageReceive(FriendMessageSender s, Message[] e)
{
//MGetPlainStringSplit() 是一个关于Message类的数组扩展方法,
//用于返回信息里的文字部分后按照 Splitor进行分割, splitor默认是空格
var sx = e.MGetPlainStringSplit();
var sendto = s.id;
var (t,j) = sx[0] switch
{
//使用信息类的扩展发送方法
"重复" => new Message[] { new Plain(sx[1]) }.SendToFriend(sendto,ClientX.c),
};
Console.WriteLine(j);
}
}
}
到现在为止, 您可以尝试发送给您的机器人一个消息, 内容如下: 重复 这句话
您的机器人应该回复: 这句话
~至此,被动处理消息已经完成
您可以使用消息发送功能主动
朝某个端的好友/群/陌生人发送消息.
例如下例的整点报时系统.
using System;
using MeowMiraiLib.Msg;
using MeowMiraiLib.Msg.Type;
MeowMiraiLib.Client c = new("ws://test.com.cn:8888/all?verifyKey=123456&qq=1234567", true, true);
c.Connect();
System.Timers.Timer t = new(1000*60); //每一分钟查看一次
t.Start(); //启动计时器
t.Elapsed += (s,e) =>
{
if(DateTime.Now.Minute == 0) //检测当前的分钟是否为0 (整点)
{
//发送信息给某个人..
new FriendMessage(/*qq号*/, new Message[] { new Plain($"{DateTime.Now.Hour}点 啦!") }).Send(c);
}
};
while (true)
{
switch (Console.ReadLine()) // 控制台操作
{
//.....
}
}
您也未必需要都写在顶级语句内, 您可以
自己规定发送形式
, 以及其他的任何程序处理逻辑.
如上例的计时器可以完全写在另一个类内.
但您要注意, 您无法获得顶级语句内的任何变量,
所以我们建议在外域(其他类) 定 义 端
, 然后在顶级语句使用完全限定名称引用.
简单的说, 没有任何关系, 任何一组信息
, 可以被任何端发送.
您可以使用扩展方法 Message[].Send(Client,Type,SendTo)
.
一组信息可以发送给群也可以发送给人, 所以需要类型, 当完全明确的时候,
我们建议使用 MessageType*.Send()
, 而不是使用 Message[].Send()
本章节主要讨论生成的事件和一些通用事件的处理方案
包含端类型
,仅通知类型
,需要决断类型
和用户定义类型
.
端发送的信息例如, 已连接, 已断开, 正在重试,出错..等, 都是由日志直接打印
其事件定义在 ./Client/ClientEvent.cs 文件的 /*--Type of Service--*/行后
端通知的通知类型如 客户端下线,Bot被邀请加入群聊,客户端网络无法连接(内网程序)...等
均由事件推送,并不会打印日志,除非您在构造时设置 Client.EventDebug = true
其事件定义在 ./Client/ClientEvent.cs 文件的 /*--Type of Event--*/ 行后
在仅通知类型内,有些需要我们做出决断,例如是否加群等
下例便展示了 只要符合某条件的(本例中为邀请信息为123456)
则加入,其他拒绝
//下列参数 c 为要发送的端,而且必须是接收这个信息的端
//老写法[通用写法] (需要 using MeowMiraiLib.Msg;)
c.OnEventBotInvitedJoinGroupRequestEvent += (s) =>
{
if(s.message == "123456") //某个条件
{
new Resp_botInvitedJoinGroupRequestEvent(s.eventId, s.fromId, s.groupId, 0, "").Send(c); //0为同意
}
else
{
new Resp_botInvitedJoinGroupRequestEvent(s.eventId, s.fromId, s.groupId, 1, "").Send(c); //1为同意
}
};
//扩展写法 (需要 using MeowMiraiLib.Event;)
c.OnEventBotInvitedJoinGroupRequestEvent += (s) =>
{
if(s.message == "123456") //某个条件
{
s.Grant(c);
}
else
{
s.Deny(c);
}
};
//你也可以接受回值查看是否成功
//.....
var (t,j) = s.Grant(c);
Console.WriteLine(j);
//.....
目前用户定义类型事件已经合并到返回值中处理,您也可以尝试重写暴露出来的Websocket端(client
.ws.DataReceived事件)
例如获取群列表等用户操作类型, 请执行 var (t,j) = new *Type*
.Send();
所有消息都继承自 Message.cs 的 Message 类,
继承时检查是否符合其他已经继承类的特性(字段/属性)
使用如下代码扩展
public class NewMessageType : Message //..Plain
{
//...字段(属性)
//...方法
}
所有未知的事件处理都由 Client实例的 事件代理 _OnUnknownEvent触发 (ClientEvent.cs文件内)
此事件代理含有一个 string 的内参, 负责传输标准的 Json字符串.
如果您知道这是个什么类型,为什么传输,您可以自己捕获然后自己处理.
3.0.0 加装了异步处理的标准流程, 优化了事件处理, 独立(实例了)端和信息发送的方案.
4.0.0 更新了异步处理的标准流程,防止CPU空转等待
4.1.0 更新到.net 6
使用更简单书写方案来控制程序, 增加了扩展方法
WebSocketClientRecieve
| => Client.Ws_MessageReceived {./Client/ClientParser.cs}
|| => EventName .Invoke() {./Client/ClientEvent.cs}
||| => User _Lambda() ...
...
User .Send() / .SendAsync()
| => Client.SSM.type.Construct() {./SSM.cs}
|| => Client.SendAndWaitResponse() {./Client/Client.cs}
|| => Wait...*
||| => User._Return_JObject
//调用方案 (扩展)
rinko.OnFriendMessageReceive += (s, e) =>
{
if(s.id != qqid) //过滤自己发出的信息
{
var str = e.MGetPlainString();
Console.WriteLine(str);
}
};
//调用方案 (方法)
MGetPlainString(message:array)
//调用方案 (扩展)
rinko.OnFriendMessageReceive += (s, e) =>
{
if(s.id != qqid) //过滤自己发出的信息
{
var str = e.MGetPlainStringSplit(); //默认使用空格分隔
//var str = e.MGetPlainStringSplit(","); //使用逗号分割
Console.WriteLine(str);
}
};
//调用方案 (方法)
MGetPlainStringSplit(message:array,spiltor:string)
//调用方案 (扩展)
rinko.OnFriendMessageReceive += (s, e) =>
{
if(s.id != qqid) //过滤自己发出的信息
{
var sx = e.MGetEachImageUrl();
Console.WriteLine(sx[1].url);
}
};
//调用方案 (方法)
MGetEachImageUrl(message:array)