Cocoa Framework 2

(没错已经是第二代了)

原本是自己机器人的一部分,后面发现可以独立成一个框架于是就这么摸出来了
基本都是在实现自己想要的东西,但我相信其中很多功能你也会喜欢~

项目地址:https://github.com/Miyakowww/CocoaFramework2
NuGet 地址:https://www.nuget.org/packages/Maila.Cocoa.Framework
交流群:766230870

后面是对一部分功能的介绍和相关案例。出于篇幅原因,某些细节会被省略,详细内容还请参阅 Cocoa Framework 文档

回复消息

Cocoa Framework 里存在 Module 概念,类似于一个个小插件,用于承载具体功能

using Maila.Cocoa.Framework; [BotModule] public class Hello : BotModuleBase { }

一个特性加一个继承就够了。接下来是添加回复消息的代码

using Maila.Cocoa.Framework; [BotModule] public class Hello : BotModuleBase { [TextRoute("hello cocoa")] public static void Run(MessageSource src) { src.Send("Hi!"); } }

TextRoute 是路由的一种,在这里的意思是接收到 “hello cocoa” 时调用相关方法。MessageSource 表示消息来源,mirai 中发送群消息和发送私聊消息的 API 不一样,因此 MessageSource 会根据消息来源自动选择相应的 API。不管是私聊还是群聊,Send() 就完事了。
当然,还有更简便的写法

using Maila.Cocoa.Framework; [BotModule] public class Hello : BotModuleBase { [TextRoute("hello cocoa")] public static string Run() => "Hi!"; }

如果返回值是 string 的话,框架会自动帮你发送

上下文

Cocoa Framework 中有个东西叫做 Meeting,可以提供非常流畅的上下文开发体验。这里还是推荐通过路由启动,Module 定义相关的代码就先省略了

[TextRoute("加法")] [TextRoute("sum")] public IEnumerator Proc(MessageSource src) { MessageReceiver receiver = new(); yield return receiver; src.Send("请输入第一个数"); yield return null; int a = int.Parse(receiver.Message.PlainText); src.Send("请输入第二个数"); yield return null; int b = int.Parse(receiver.Message.PlainText); src.Send($"结果是 {a + b}"); }

路由可以叠加多个,同时生效。
Meeting 基于 C# 的枚举器实现,所以返回值类型需要改成 IEnumerator 或者 IEnumerable。先 yield return 一个 MessageReceiver,用于接收消息。yield return null 时会等待目标发送消息,然后可以通过之前的 MessageReceiver 获取目标发送的消息。默认目标是最开始触发 Meeting 的人,您也可以在中途改成其他人或者某个群,把目标改成群可以用于实现狼人杀之类的游戏

数据托管

Cocoa Framework 自身的数据都会自动保存,除非程序被强制关闭。用户数据也可以交给框架一起自动保存,也就是数据托管

[Hosting] private readonly List<long> users = new();

这样框架就会保存这个 List 里的数据了,并且在程序启动时也会自动读取之前的数据填充进去,无需手动读取。就算是 readonly 的字段也没问题,唯独 static readonly 的不支持。所有类型都可以托管,自定义类型也可以

自动数据

这个解释起来有点麻烦,直接看例子吧

[RegexRoute("笔记 (?<notes>.+)")] public static string TakeNotes(string notes, UserAutoData<string?> paper) { paper.Value = notes; return "写好了!"; } [TextRoute("查看笔记")] public static string ViewNotes(UserAutoData<string?> paper) { if (paper.Value is null) { return "您没有记下任何内容"; } return paper.Value; }

先用第一个账号使用
1.png
然后用第二个账号
2.png
回到第一个账号
3.png
这里用到了另一种路由——RegexRoute,也就是通过正则表达式对消息进行判断。正则表达式中设置了组名的会将匹配出的内容自动传递到同名参数里。顺便路由方法的参数顺序可以随意更换,不会影响执行效果。
回到自动数据,可以发现每个账号之间数据是分开的。同时给到 paper.Value 的值也会被自动保存,即使软件重启也不会丢失。string? 也可以换成其他类型,跟数据托管一样。除了 UserAutoData 还有 GroupAutoData 和 SourceAutoData,一个是群之间数据分开,一个是同一个用户群聊和私聊数据分开