diff --git a/MAA_README.md b/MAA_README.md index 95e05c2..d73d203 100644 --- a/MAA_README.md +++ b/MAA_README.md @@ -43,16 +43,21 @@ MAA会以1秒的间隔持续轮询这个端点,尝试获取他要执行的任 }, { "id": "15be4725-5bd3-443d-8ae3-0a5ae789254c", //任务的唯一id,字符串类型,在汇报任务时会使用 - "type": "LinkStart", //启动一键长草 + "type": "LinkStart", //启动一键长草 }, { "id": "15be4725-5bd3-443d-8ae3-0a5ae789254c", //任务的唯一id,字符串类型,在汇报任务时会使用 - "type": "LinkStart-Recruiting", //一键长草的子功能。立即根据当前配置,单独执行一键长草中的对应子功能,无视主界面上该功能的勾选框。这一类Type的可选值为:LinkStart-Base,LinkStart-WakeUp,LinkStart-Combat,LinkStart-Recruiting,LinkStart-Mall,LinkStart-Mission,LinkStart-AutoRoguelike,LinkStart-ReclamationAlgorithm + "type": "LinkStart-Recruiting", //立即根据当前配置,单独执行一键长草中的对应子功能,无视主界面上该功能的勾选框。这一类Type的可选值详见下述 }, { "id": "b353c469-b902-4357-bd8f-d133199eea31", //任务的唯一id,字符串类型,在汇报任务时会使用 "type": "Toolbox-GachaOnce", //工具箱中的牛牛抽卡任务,该类Type的可选取值为:Toolbox-GachaOnce, Toolbox-GachaTenTimes }, + { + "id": "b353c469-b902-4357-bd8f-d133199eea31", //任务的唯一id,字符串类型,在汇报任务时会使用 + "type": "Settings-ConnectionAddress", //修改配置项的任务,等同于执行ConfigurationHelper.SetValue("ConnectionAddress", params); 为了安全起见,不是每个配置都可以修改,能修改的配置详见下述。 + "params": "value" //要修改的值 + }, ], ... // 如果你的这个端点还有其他用途,你可以自行添加可选的返回值,但是MAA只会读取tasks } @@ -61,6 +66,11 @@ MAA会以1秒的间隔持续轮询这个端点,尝试获取他要执行的任 这些任务会被按顺序执行,也就是说如果你先发下一个公招任务,再发下一个截图任务,则截图会在公招任务结束后执行。 该端点应当可以重入并且重复返回需要执行的任务,MAA会自动记录任务Id,对于相同的Id,不会重复执行。 +备注: +- LinkStart-[TaskName]型的任务type的可选值为LinkStart-Base,LinkStart-WakeUp,LinkStart-Combat,LinkStart-Recruiting,LinkStart-Mall,LinkStart-Mission,LinkStart-AutoRoguelike,LinkStart-ReclamationAlgorithm +- Settings-[SettingsName]型的任务的type的可选值为Settings-ConnectionAddress +- Settings系列任务仍然是要按顺序执行的,并不会在收到任务的时候立刻执行,而是排在上一个任务的后面。 + ## 汇报任务端点 每当MAA执行完一个任务,他就会通过该端点将任务的执行结果汇报给远端。 diff --git a/README.md b/README.md index 837547d..2bdfe75 100644 --- a/README.md +++ b/README.md @@ -2,21 +2,22 @@ **财产损失警告!MAA控制的是你真实的明日方舟账户。尽管MAA的开发者和本插件的开发者尽了最大努力,但是程序开发不可避免的存在Bug。因此,对于使用MAA,以及本插件,所造成的的财产损失,本插件的开发者,以及MAA的开发者概不负责。** +**喜报!远程控制功能已经正式加入官方MAA,从最新版的v4.25.0开始,可以直接使用官方MAA对接此插件进行控制。** + **和MAA的对接需要大量测试!希望各位用户和开发者,能够尽可能多在Github上提Issue,不管是提交Bug,还是推荐新的功能。(不过我只有每天晚上有时间写代码呜呜呜)** -如果你发现MAA在远控时执行逻辑有问题,比如说“执行完十连抽后执行基建排班会导致页面卡死,因为基建排班功能不能从抽卡页面起始。”这样的bug,也请汇报给我,让我修改兔兔插件的任务下发逻辑,比如在基建排班之前插入一个唤醒之类的。 +如果你发现MAA在远控时执行逻辑有问题,比如说“执行完十连抽后执行基建排班会导致页面卡死,因为基建排班功能不能从抽卡页面起始。”这样的bug,也请汇报给我,让我修改兔兔插件的任务下发逻辑,比如在基建排班之前插入一个唤醒,或者调整MAA的相关代码之类的。 ## 更新提示 -2.0版本起,不再使用独立开发的被控端,转而使用一个特制的WindowsWPF版MAA客户端。用来防止各种各样的连接问题。 - -**新旧插件不兼容!**如果你发现新版本有问题,并且旧版本可以使用,你可以先暂时使用旧版插件以及旧版被控端。 - +2.0版本起,将直接使用MAA的远程控制功能。**新旧插件不兼容!**,因为MAA已经正式支持远控,建议所有用户放弃旧版插件。 现在,再连不上模拟器,就去找玛丽报Bug吧:-) +2.2版本加入了切换连接地址的命令。 + ## 这是什么 -1. 安装了该插件以后,使用一个特殊版本的MAA,可以实现通过兔兔聊天控制MAA。 +1. 安装了该插件以后,可以实现通过兔兔聊天控制MAA。 2. 每个群友需要自己启动模拟器和安装配置MAA。 3. 兔兔部署者则需要提供一个公网域名或者IP,以供群友的被控端连接。 4. 安装该插件后,插件会检查你的链接密钥,就是连接Console填写的那个,**如果这个密钥强度不够,则不允许使用本功能**。这是为了防止兔兔被暴露到公网后,出现各种安全隐患。密钥要求必须要有一个大写字母,一个小写字母,一个数字和一个特殊符号,并且要8位以上。 @@ -34,7 +35,7 @@ 如果你还不知道MAA的话,快去下面的链接看看吧。 -[快去给玛丽点赞把](https://github.com/MaaAssistantArknights/MaaAssistantArknights) +[快去给玛丽点赞吧](https://github.com/MaaAssistantArknights/MaaAssistantArknights) ## 如何使用 @@ -43,24 +44,22 @@ 1. 首先您需要到控制台的设置页面填入您的公网ip地址和域名,就像填写在控制台里的那样。 2. 然后,然后就完事了,剩下的就交给兔兔。 -3. 有条件的话,建议最好去Github上下载这个特制的MAA.exe并放到群文件里,因为Github有些地方的人可能打不开。 - [特制MAA下载地址](https://github.com/hsyhhssyy/amiyabot-arknights-hsyhhssyy-maa/releases/) +**注意,目前版本的兔兔,Web服务启动时,有可能会出现顺序异常导致服务不生效,具体表现为有人访问/maa/getTask或/maa/reportStatus时报告404NotFound,兔兔会在未来版本修复此问题。目前遇到时请重启兔兔,还不行的话多重启几次就会好,一旦没问题了,只要兔兔不关闭,就不会再出问题。** 我是兔兔的群友 -1. 首先你需要下载安装一个MAA,目前仅支持Windows版本。 -2. 你需要下载特殊版本的MAA.exe文件并用它替换MAA文件夹下的对应文件。 -3. 启动这个特制的MAA,确定能用它连接模拟器并配置好了各项功能。至少配置好一键长草并确定可以执行。具体流程请参照MAA的教程。 -4. 打开MAA的设置,进入“远程控制”,在用户标识符中填入你的QQ号。 -5. 如果设备标识符为空,按一下旁边的重新生成按钮,生成一个。 -6. 在群聊中说`兔兔如何连接MAA`,兔兔会回复你要填写的地址。 -7. 将兔兔说的地址,填写到MAA中`远程控制`设置的`获取任务端点`和`汇报任务端点`文本框里 -8. 复制设备标识符,然后到群里,说`兔兔记录MAA设备<设备标识符>`让兔兔记住。不必担心其他人看到,他们就算复制了这个标识符也没用。 +1. 首先你需要下载安装一个MAA,目前仅支持Windows版本的MAA。 +2. 启动MAA,确定能用它连接模拟器并配置好了各项功能。至少配置好一键长草并确定可以执行。具体流程请参照MAA的教程。 +3. 打开MAA的设置,进入“远程控制”,在用户标识符中填入你的QQ号。 +4. 如果设备标识符为空,按一下旁边的重新生成按钮,生成一个。 +5. 在群聊中说`兔兔如何连接MAA`,兔兔会回复你要填写的地址。 +6. 将兔兔说的地址,填写到MAA中`远程控制`设置的`获取任务端点`和`汇报任务端点`文本框里 +7. 复制设备标识符,然后到群里,说`兔兔记录MAA设备<设备标识符>`让兔兔记住。不必担心其他人看到,他们就算复制了这个标识符也没用。 - ![记住密钥](https://raw.githubusercontent.com/hsyhhssyy/amiyabot-arknights-hsyhhssyy-maa/master/docs/remember_did.png) +![记住密钥](https://raw.githubusercontent.com/hsyhhssyy/amiyabot-arknights-hsyhhssyy-maa/master/docs/remember_did.png) -9. 接下来就是挂机,然后去群聊里和兔兔聊天吧。 +8. 接下来就是挂机,然后去群聊里和兔兔聊天吧。 ## 兔兔支持的命令 @@ -94,6 +93,12 @@ | 兔兔MAA十连抽 | 进行一次十连抽(这是真实抽卡!) | 2.1 | | 兔兔MAA单抽 | 进行一次单抽(这是真实抽卡!) | 2.1 | +### 修改配置子功能 + +| 命令 | 说明 | 引入版本 | +| ---- | ---- | ---- | +| 兔兔MAA切换连接地址emulator-5554 | 修改`设置->连接设置->连接地址`配置项的值,可用于切换模拟器。使用时连接地址紧跟在命令后。 | 2.2 | + **任务会按顺序执行,如果你下发了一个无限持续的任务(比如刷999999把肉鸽),那你后续的指令都不会生效了。** 截图存储在resource/maa-adapter/screenshots文件夹下,请注意定时清理。 @@ -102,22 +107,26 @@ ## 我也想做一个控制端 -如果也想要利用这个特制的MAA.exe实现一个自己的控制端,你可以 [看这里](https://github.com/hsyhhssyy/amiyabot-arknights-hsyhhssyy-maa/blob/master/MAA_README.md) +现在可以去看MAA的[官方开发文档]( +https://maa.plus/docs/3.8-%E8%BF%9C%E7%A8%8B%E6%8E%A7%E5%88%B6%E5%8D%8F%E8%AE%AE.html)来了解如何开发控制端了。 + ## 鸣谢 > [插件项目地址:Github](https://github.com/hsyhhssyy/amiyabot-arknights-hsyhhssyy-maa/) -> [被控端项目地址:Github](https://github.com/hsyhhssyy/amiyabot-maa-adapter/) - > [遇到问题可以在这里反馈(Github)](https://github.com/hsyhhssyy/amiyabot-arknights-hsyhhssyy-maa/issues/new/) > [如果上面的连接无法打开可以在这里反馈(Gitee)](https://gitee.com/hsyhhssyy/amiyabot-plugin-bug-report/issues/new) -> [Logo作者:Sesern老师](https://space.bilibili.com/305550122) +> Logo作者: Stable-Diffusion | 版本 | 变更 | | ---- | ---- | | 1.0 | 内部测试版本 | | 1.1 | 提高了功能函数的优先级防止被公招功能覆盖,现在一键长草会说出下发的具体任务 | -| 1.2 | 修改了检测秘钥的代码,输出更友好的信息 | \ No newline at end of file +| 1.2 | 修改了检测秘钥的代码,输出更友好的信息 | +| 2.0 | 大幅修改并使用MAA自身来进行远控 | +| 2.1 | 增加功能,并提供针对官方版MAA的说明 | +| 2.2 | 增加功能 | +| 2.3 | 适配新版兔兔 | \ No newline at end of file diff --git a/README_USE.md b/README_USE.md index eae1998..3683224 100644 --- a/README_USE.md +++ b/README_USE.md @@ -1,14 +1,13 @@ ## 如何连接 -1. 首先你需要下载安装一个MAA,目前仅支持Windows版本。 -2. 你需要下载特殊版本的MAA.exe文件并用它替换MAA文件夹下的对应文件。 -3. 启动这个特制的MAA,确定能用它连接模拟器并配置好了各项功能。至少配置好一键长草并确定可以执行。具体流程请参照MAA的教程。 -4. 打开MAA的设置,进入“远程控制”,在用户标识符中填入你的QQ号。 -5. 如果设备标识符为空,按一下旁边的重新生成按钮,生成一个。 -6. 在群聊中说`兔兔如何连接MAA`,兔兔会回复你要填写的地址。 -7. 将兔兔说的地址,填写到MAA中`远程控制`设置的`获取任务端点`和`汇报任务端点`文本框里 -8. 复制设备标识符,然后到群里,说`兔兔记录MAA设备<设备标识符>`让兔兔记住。不必担心其他人看到,他们就算复制了这个标识符也没用。 -9. 接下来就是挂机,然后去群聊里和兔兔聊天吧。 +1. 首先你需要下载安装一个MAA,目前仅支持Windows版本的MAA。 +2. 启动MAA,确定能用它连接模拟器并配置好了各项功能。至少配置好一键长草并确定可以执行。具体流程请参照MAA的教程。 +3. 打开MAA的设置,进入“远程控制”,在用户标识符中填入你的QQ号。 +4. 如果设备标识符为空,按一下旁边的重新生成按钮,生成一个。 +5. 在群聊中说`兔兔如何连接MAA`,兔兔会回复你要填写的地址。 +6. 将兔兔说的地址,填写到MAA中`远程控制`设置的`获取任务端点`和`汇报任务端点`文本框里 +7. 复制设备标识符,然后到群里,说`兔兔记录MAA设备<设备标识符>`让兔兔记住。不必担心其他人看到,他们就算复制了这个标识符也没用。 +8. 接下来就是挂机,然后去群聊里和兔兔聊天吧。 ## 兔兔支持的命令 @@ -42,4 +41,10 @@ | 兔兔MAA十连抽 | 进行一次十连抽(这是真实抽卡!) | 2.1 | | 兔兔MAA单抽 | 进行一次单抽(这是真实抽卡!) | 2.1 | +### 修改配置子功能 + +| 命令 | 说明 | 引入版本 | +| ---- | ---- | ---- | +| 兔兔MAA切换连接地址emulator-5554 | 修改`设置->连接设置->连接地址`配置项的值,可用于切换模拟器。使用时连接地址紧跟在命令后。 | 2.2 | + **任务会按顺序执行,如果你下发了一个无限持续的任务(比如刷999999把肉鸽),那你后续的指令都不会生效了。** \ No newline at end of file diff --git a/logo.png b/logo.png index 28b3bc2..9d34037 100644 Binary files a/logo.png and b/logo.png differ diff --git a/main.py b/main.py index af78114..760afdc 100644 --- a/main.py +++ b/main.py @@ -9,7 +9,7 @@ from amiyabot import Message, Chain from core.util import check_file_content -from core.customPluginInstance import AmiyaBotPluginInstance +from core import AmiyaBotPluginInstance from .server import server_api from .server.server_api import external_adapters @@ -41,10 +41,10 @@ def install(self): bot = MaaAdapterPluginInstance( name='MAA对接器', - version='2.1', + version='2.3', plugin_id='amiyabot-arknights-hsyhhssyy-maa', plugin_type='', - description='用于对接MAA', + description='MAA远程控制功能控制端的兔兔实现', document=f'{curr_dir}/README.md', instruction=f'{curr_dir}/README_USE.md', global_config_default=f'{curr_dir}/configs/global_config_default.json', @@ -62,7 +62,7 @@ async def get_connection(data: Message): AmiyaBotMAAConnection.user_id == data.user_id) if conn is None: - await data.send(Chain(data).text('博士,您还没有绑定连接秘钥。')) + await data.send(Chain(data).text('博士,您还没有绑定连接秘钥。请发送"兔兔如何连接MAA"查看如何绑定。')) return False, None if conn.validated == False: @@ -81,9 +81,9 @@ async def maa_start(data: Message): conn_str = bot.get_config("connection_string").rstrip("/") if conn_str is None or conn_str == "": - return Chain(data, at=False).text('博士,兔兔没有设置连接地址哦。') + return Chain(data, at=False).text('博士,兔兔没有设置连接地址,请联系兔兔管理员。') - instStr = f'获取任务端点是: {conn_str}/maa/getTask \n汇报任务端点是: {conn_str}/maa/reportStatus \n特制的Maa.exe下载地址是: https://github.com/hsyhhssyy/amiyabot-arknights-hsyhhssyy-maa/releases/' + instStr = f'获取任务端点是: {conn_str}/maa/getTask \n汇报任务端点是: {conn_str}/maa/reportStatus' return Chain(data, at=False).markdown(check_file_content(f'{curr_dir}/README_USE.md')).text(instStr) @@ -125,6 +125,29 @@ async def message_loop(): def create_my_message_filter_lambda(original_data): return lambda data: data.user_id == original_data.user_id +@bot.on_message(keywords=['MAA强制停止'], level=5) +async def maa_fight(data: Message): + + valid, conn = await get_connection(data) + + if not valid: + return + + task_uuid = str(uuid.uuid4()) + AmiyaBotMAATask.create(connection=conn.id, uuid=task_uuid, type="StopTask", + parameter=None, status="ASSIGNED", create_at=datetime.now()) + + async def message_loop(): + while True: + await asyncio.sleep(1) + task = AmiyaBotMAATask.get(AmiyaBotMAATask.uuid == task_uuid) + # log.info(f'{task.payload}') + if task.status == "SUCCESS": + await data.send(Chain(data).text(f'博士,当前正在进行的任务已停止。')) + return + + asyncio.create_task(message_loop()) + @bot.on_message(keywords=['MAA截图'], level=5) async def maa_fight(data: Message): @@ -141,14 +164,52 @@ async def maa_fight(data: Message): wait_snapshot(data,task_uuid) -async def assign_simple_task_with_snapshot(data,maa_type,mission_str): +@bot.on_message(keywords=['MAA立即截图'], level=5) +async def maa_fight(data: Message): + + valid, conn = await get_connection(data) + + if not valid: + return + + task_uuid = str(uuid.uuid4()) + AmiyaBotMAATask.create(connection=conn.id, uuid=task_uuid, type="CaptureImageNow", + parameter=None, status="ASSIGNED", create_at=datetime.now()) + + wait_snapshot(data,task_uuid) + +@bot.on_message(keywords=['MAA当前任务'], level=5) +async def maa_fight(data: Message): + + valid, conn = await get_connection(data) + + if not valid: + return + + task_uuid = str(uuid.uuid4()) + AmiyaBotMAATask.create(connection=conn.id, uuid=task_uuid, type="HeartBeat", + parameter=None, status="ASSIGNED", create_at=datetime.now()) + + async def message_loop(): + while True: + await asyncio.sleep(1) + task = AmiyaBotMAATask.get(AmiyaBotMAATask.uuid == task_uuid) + # log.info(f'{task.payload}') + if task.payload is not None and task.payload != "": + currentTask = AmiyaBotMAATask.get(AmiyaBotMAATask.uuid == task.payload) + await data.send(Chain(data).text(f'博士,当前正在进行的任务是:{currentTask.type}。')) + return + + asyncio.create_task(message_loop()) + +async def assign_simple_task_with_snapshot(data,maa_type,mission_str,parameter=""): valid, conn = await get_connection(data) if not valid: return AmiyaBotMAATask.create(connection=conn.id, uuid=str(uuid.uuid4()), type=maa_type, - parameter="", status="ASSIGNED", create_at=datetime.now()) + parameter=parameter, status="ASSIGNED", create_at=datetime.now()) snapshot_task_uuid = str(uuid.uuid4()) AmiyaBotMAATask.create(connection=conn.id, uuid=snapshot_task_uuid, type="CaptureImage", @@ -158,6 +219,17 @@ async def assign_simple_task_with_snapshot(data,maa_type,mission_str): return Chain(data).text(f'博士,{mission_str}任务已布置,干员们会努力做好罗德岛的日常工作的,任务结束后将发送截图给您。') +async def assign_simple_task(data,maa_type,mission_str,parameter=""): + + valid, conn = await get_connection(data) + if not valid: + return + + AmiyaBotMAATask.create(connection=conn.id, uuid=str(uuid.uuid4()), type=maa_type, + parameter=parameter, status="ASSIGNED", create_at=datetime.now()) + + return Chain(data).text(f'博士,{mission_str}任务已布置,干员们会努力做好罗德岛的日常工作的。') + @bot.on_message(keywords=['MAA一键长草'], level=5) async def maa_fight(data: Message): return await assign_simple_task_with_snapshot(data,"LinkStart","一键长草") @@ -244,4 +316,17 @@ async def maa_gacha(data: Message): else: await data.send(Chain(data).text('博士,单次寻访任务已取消')) - return \ No newline at end of file + return + +@bot.on_message(keywords=['MAA切换连接地址'], level=5) +async def maa_fight(data: Message): + + pattern = r"MAA切换连接地址([\s\S]*)" + + match = re.search(pattern, data.text_original) + if match: + newStr = match.group(1) + return await assign_simple_task(data,"Settings-ConnectAddress","切换连接地址",newStr) + else: + return Chain(data).text(f'博士,您没有提供连接地址。') + diff --git a/server/server_api.py b/server/server_api.py index 9182b1d..e01b9f2 100644 --- a/server/server_api.py +++ b/server/server_api.py @@ -86,6 +86,8 @@ async def report_status(self, data: ReportStatusModel): f.write(base64.b64decode(data.payload)) task.payload = f'{screenshot_dir}/{task.uuid}.png' log.info(f'{task.payload}') + else: + task.payload = data.payload task.save()