Coder Social home page Coder Social logo

graiaproject / ariadne Goto Github PK

View Code? Open in Web Editor NEW
699.0 6.0 46.0 3.58 MB

一个优雅且完备的 Python QQ 自动化框架,基于 Mirai API HTTP v2。 Powered by Graia Project.

Home Page: https://graia.cn/ariadne

License: GNU Affero General Public License v3.0

Python 100.00%
python asyncio graia framework qq qqbot bot ariadne graiaproject mirai

ariadne's Introduction

Ariadne

Another elegant framework for mirai and mirai-api-http v2.

接受当下, 面向未来.

PyPI Python Version

Code style: black Imports: isort License pdm-managed

文档 docs docs docs
API 参考 docs docs docs

本项目适用于 mirai-api-http 2.0 以上版本.

Ariadne 是 Graia Project 继承了 Application 并进行了许多改进后产生的作品, 相信它可以给你带来良好的 Python QQ Bot 开发体验.

注意, 本框架需要 mirai-api-http v2.

安装

pdm add graia-ariadne

poetry add graia-ariadne

pip install graia-ariadne

我们强烈建议使用 pdm / poetry 进行包管理

开始使用

from graia.ariadne.app import Ariadne
from graia.ariadne.connection.config import config
from graia.ariadne.model import Friend

app = Ariadne(config(verify_key="ServiceVerifyKey", account=123456789))


@app.broadcast.receiver("FriendMessage")
async def friend_message_listener(app: Ariadne, friend: Friend):
    await app.send_message(friend, "Hello, World!")


Ariadne.launch_blocking()

更多信息请看 快速开始

讨论

QQ 交流群: 邀请链接

QQ 群不定时清除不活跃成员, 请自行重新申请入群.

文档

API 文档 官方文档 社区文档 鸣谢

如果认为本项目有帮助, 欢迎点一个 Star.

协议

本项目以 GNU AGPL-3.0 作为开源协议, 这意味着你需要遵守相应的规则.

持续集成 (CI) 状态

API Doc Status pre-commit.ci status

API 文档构建 发布

参与开发

贡献指南

ariadne's People

Contributors

bili-nullptr avatar blueglassblock avatar dependabot[bot] avatar github-actions[bot] avatar greyelaina avatar i-love-study avatar mingxuangame avatar pre-commit-ci[bot] avatar programripper avatar redlnn avatar rf-tar-railt avatar socialsisteryi avatar yuasds avatar zhaozuohong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ariadne's Issues

[Bug]使用MultimediaMixin.uploadImage上传图像并获得Image对象时出现异常

问题
使用MultimediaMixin.uploadImage上传图像并获得Image对象时出现异常,经调试发现call_api(Http那个)函数中

for k, v in data:
                form.add_fields(k, v)

语句报错,将该语句改为

for k, v in data.items():
        form.add_field(k, v)

后异常消失,行为恢复正常

如何复现
使用MultimediaMixin.uploadImage上传任意图像

预期行为
获得Image对象并发出

使用环境:

  • 系统: Windows 10 专业版
  • MAH 版本: v2.3.3
  • Ariadne 版本:0.3.7
  • Python 版本:3.10
  • 其他 Graia 库版本:默认版本
  • 其他 有关 库版本: 默认版本

日志/截图
image

[Half Permanent] Code Quality Improvement

目前 Ariadne 的代码库存在大量被 static type checker 认为是错误的地方,

应该使用 flake8 / pylance 等工具进行代码风格的进一步检查.

[Feature] ArgumentSparkle

使用场景.
使Twilight支持子命令

你想要的解决方案
在最后的 Sparkle Class 内塞入 SubSparkle Class

是否已有相关实现
Cesloi-Aloconna graiax-msgparse

其他内容

[Feature] “开发者工具之热重启”

使用场景
在使用Ariadne开发过程中,自动重启,提升开发效率

你想要的解决方案
使用 watchgod 监控工作区文件变动,从而实现自动重启

相关简单实现

import asyncio,os
from graia.broadcast import Broadcast
from graia.ariadne.app import Ariadne
from graia.ariadne.message.chain import MessageChain
from graia.ariadne.message.element import Plain
from graia.ariadne.model import Friend, MiraiSession

loop = asyncio.get_event_loop()
bcc = Broadcast(loop = loop)
miraisession = MiraiSession(host="http://localhost:8080", account=123456789, verify_key="123456789")

app = Ariadne(
    connect_info=miraisession,
    loop=loop,
    broadcast=bcc,
    )

@bcc.receiver("FriendMessage")
async def friend_message_listener(app: Ariadne, friend: Friend):
    await app.sendMessage(friend, MessageChain.create([Plain("Hello, World!")]))
    
from watchgod import arun_process

def reload():
    loop.run_until_complete(app.lifecycle())

async def watchfile():
    await arun_process(os.getcwd(), reload)

if __name__ == "__main__":
    loop.create_task(watchfile())
    loop.run_until_complete(app.lifecycle())

其他内容
watchgod

[Bug] 当消息链中的 App 元素用 asPersistentString() 转换得到字符串再用 fromPersistentString() 转换回来会报错

问题
B站分享的App消息用 asPersistentString() 转换得到字符串,再用 fromPersistentString() 转换为消息链时会报错

如何复现
使用 fromPersistentString()这个字符串(pastebin 有效期一周)转换为消息链会报 json.decoder.JSONDecodeError 错误

预期行为
不报错~

使用环境:

  • 系统: Windows 11
  • MAH 版本: 2.3.3
  • Ariadne 版本: 0.4.0-a9
  • Python 版本: 3.10
  • 其他 Graia 库版本: bcc 0.13.2
  • 其他 有关 库版本:

日志/截图
}~7$~AW86N`R}67_M97ZONW

[Bug]在“在一个非套接字上尝试了一个操作。”后直接退出程序了

问题

--- Logging error ---
--- Logging error ---
2021-11-10 23:58:18.436 | ERROR    | graia.ariadne.util:loguru_excepthook:64 - Uncaught Exception:
Traceback (most recent call last):

  File "D:\Python39\lib\asyncio\events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
    │    │            │    │           │    └ <member '_args' of 'Handle' objects>
    │    │            │    │           └ <Handle _ProactorBasePipeTransport._call_connection_lost(None)>
    │    │            │    └ <member '_callback' of 'Handle' objects>
    │    │            └ <Handle _ProactorBasePipeTransport._call_connection_lost(None)>
    │    └ <member '_context' of 'Handle' objects>
    └ <Handle _ProactorBasePipeTransport._call_connection_lost(None)>

  File "D:\Python39\lib\asyncio\proactor_events.py", line 162, in _call_connection_lost
    self._sock.shutdown(socket.SHUT_RDWR)
    │    │     │        │      └ 2
    │    │     │        └ <module 'socket' from 'D:\\Python39\\lib\\socket.py'>
    │    │     └ <method 'shutdown' of '_socket.socket' objects>
    │    └ <socket.socket fd=-1, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6>
    └ <_ProactorSocketTransport closing fd=-1>

OSError: [WinError 10038] 在一个非套接字上尝试了一个操作。


During handling of the above exception, another exception occurred:


Traceback (most recent call last):

  File "D:\Python39\lib\logging\__init__.py", line 1083, in emit
    msg = self.format(record)
          │    │      └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1738, "Exception in callback _ProactorBasePipeTransport._cal...
          │    └ <function Handler.format at 0x0000020E516DF310>
          └ <_StderrHandler <stderr> (WARNING)>

  File "D:\Python39\lib\logging\__init__.py", line 927, in format
    return fmt.format(record)
           │   │      └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1738, "Exception in callback _ProactorBasePipeTransport._cal...
           │   └ <function Formatter.format at 0x0000020E516E1670>
           └ <logging.Formatter object at 0x0000020E51642940>

  File "D:\Python39\lib\logging\__init__.py", line 671, in format
    record.exc_text = self.formatException(record.exc_info)
    │      │          │    │               │      └ (<class 'OSError'>, OSError(10038, '在一个非套接字上尝试了一个操作。', None, 10038, None), <traceback object at 0x0000020E575F7500>)
    │      │          │    │               └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1738, "Exception in callback _ProactorBasePipeTransport._cal...
    │      │          │    └ <function Formatter.formatException at 0x0000020E516E1430>
    │      │          └ <logging.Formatter object at 0x0000020E51642940>
    │      └ None
    └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1738, "Exception in callback _ProactorBasePipeTransport._cal...

  File "D:\Python39\lib\logging\__init__.py", line 621, in formatException
    traceback.print_exception(ei[0], ei[1], tb, None, sio)
    │         │               │      │      │         └ <_io.StringIO object at 0x0000020E57DD3670>
    │         │               │      │      └ <traceback object at 0x0000020E575F7500>
    │         │               │      └ (<class 'OSError'>, OSError(10038, '在一个非套接字上尝试了一个操作。', None, 10038, None), <traceback object at 0x0000020E575F7500>)
    │         │               └ (<class 'OSError'>, OSError(10038, '在一个非套接字上尝试了一个操作。', None, 10038, None), <traceback object at 0x0000020E575F7500>)
    │         └ <function loguru_print_exception at 0x0000020E53D431F0>
    └ <module 'traceback' from 'D:\\Python39\\lib\\traceback.py'>

TypeError: loguru_print_exception() missing 1 required positional argument: 'chain'


During handling of the above exception, another exception occurred:


Traceback (most recent call last):

  File "D:\Python39\lib\asyncio\base_events.py", line 1764, in call_exception_handler
    self.default_exception_handler(context)
    │    │                         └ {'message': 'Exception in callback _ProactorBasePipeTransport._call_connection_lost(None)', 'exception': OSError(10038, '在一个非...
    │    └ <function BaseEventLoop.default_exception_handler at 0x0000020E532559D0>
    └ <ProactorEventLoop running=False closed=False debug=False>

  File "D:\Python39\lib\asyncio\base_events.py", line 1738, in default_exception_handler
    logger.error('\n'.join(log_lines), exc_info=exc_info)
    │      │               │                    └ (<class 'OSError'>, OSError(10038, '在一个非套接字上尝试了一个操作。', None, 10038, None), <traceback object at 0x0000020E575F7500>)
    │      │               └ ['Exception in callback _ProactorBasePipeTransport._call_connection_lost(None)', 'handle: <Handle _ProactorBasePipeTransport....
    │      └ <function Logger.error at 0x0000020E516E6940>
    └ <Logger asyncio (WARNING)>

  File "D:\Python39\lib\logging\__init__.py", line 1475, in error
    self._log(ERROR, msg, args, **kwargs)
    │    │    │      │    │       └ {'exc_info': (<class 'OSError'>, OSError(10038, '在一个非套接字上尝试了一个操作。', None, 10038, None), <traceback object at 0x0000020E575F75...
    │    │    │      │    └ ()
    │    │    │      └ 'Exception in callback _ProactorBasePipeTransport._call_connection_lost(None)\nhandle: <Handle _ProactorBasePipeTransport._ca...
    │    │    └ 40
    │    └ <function Logger._log at 0x0000020E516E6CA0>
    └ <Logger asyncio (WARNING)>

  File "D:\Python39\lib\logging\__init__.py", line 1589, in _log
    self.handle(record)
    │    │      └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1738, "Exception in callback _ProactorBasePipeTransport._cal...
    │    └ <function Logger.handle at 0x0000020E516E6D30>
    └ <Logger asyncio (WARNING)>

  File "D:\Python39\lib\logging\__init__.py", line 1599, in handle
    self.callHandlers(record)
    │    │            └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1738, "Exception in callback _ProactorBasePipeTransport._cal...
    │    └ <function Logger.callHandlers at 0x0000020E516E6F70>
    └ <Logger asyncio (WARNING)>

  File "D:\Python39\lib\logging\__init__.py", line 1669, in callHandlers
    lastResort.handle(record)
    │          │      └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1738, "Exception in callback _ProactorBasePipeTransport._cal...
    │          └ <function Handler.handle at 0x0000020E516DF430>
    └ <_StderrHandler <stderr> (WARNING)>

  File "D:\Python39\lib\logging\__init__.py", line 952, in handle
    self.emit(record)
    │    │    └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1738, "Exception in callback _ProactorBasePipeTransport._cal...
    │    └ <function StreamHandler.emit at 0x0000020E516DF8B0>
    └ <_StderrHandler <stderr> (WARNING)>

  File "D:\Python39\lib\logging\__init__.py", line 1091, in emit
    self.handleError(record)
    │    │           └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1738, "Exception in callback _ProactorBasePipeTransport._cal...
    │    └ <function Handler.handleError at 0x0000020E516DF670>
    └ <_StderrHandler <stderr> (WARNING)>

  File "D:\Python39\lib\logging\__init__.py", line 1005, in handleError
    traceback.print_exception(t, v, tb, None, sys.stderr)
    │         │                               │   └ <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>
    │         │                               └ <module 'sys' (built-in)>
    │         └ <function loguru_print_exception at 0x0000020E53D431F0>
    └ <module 'traceback' from 'D:\\Python39\\lib\\traceback.py'>

TypeError: loguru_print_exception() missing 1 required positional argument: 'chain'


During handling of the above exception, another exception occurred:


Traceback (most recent call last):

  File "D:\Python39\lib\logging\__init__.py", line 1083, in emit
    msg = self.format(record)
          │    │      └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1771, "Exception in default exception handler">
          │    └ <function Handler.format at 0x0000020E516DF310>
          └ <_StderrHandler <stderr> (WARNING)>

  File "D:\Python39\lib\logging\__init__.py", line 927, in format
    return fmt.format(record)
           │   │      └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1771, "Exception in default exception handler">
           │   └ <function Formatter.format at 0x0000020E516E1670>
           └ <logging.Formatter object at 0x0000020E51642940>

  File "D:\Python39\lib\logging\__init__.py", line 671, in format
    record.exc_text = self.formatException(record.exc_info)
    │      │          │    │               │      └ (<class 'TypeError'>, TypeError("loguru_print_exception() missing 1 required positional argument: 'chain'"), <traceback objec...
    │      │          │    │               └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1771, "Exception in default exception handler">
    │      │          │    └ <function Formatter.formatException at 0x0000020E516E1430>
    │      │          └ <logging.Formatter object at 0x0000020E51642940>
    │      └ None
    └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1771, "Exception in default exception handler">

  File "D:\Python39\lib\logging\__init__.py", line 621, in formatException
    traceback.print_exception(ei[0], ei[1], tb, None, sio)
    │         │               │      │      │         └ <_io.StringIO object at 0x0000020E57DD3DC0>
    │         │               │      │      └ <traceback object at 0x0000020E579EDCC0>
    │         │               │      └ (<class 'TypeError'>, TypeError("loguru_print_exception() missing 1 required positional argument: 'chain'"), <traceback objec...
    │         │               └ (<class 'TypeError'>, TypeError("loguru_print_exception() missing 1 required positional argument: 'chain'"), <traceback objec...
    │         └ <function loguru_print_exception at 0x0000020E53D431F0>
    └ <module 'traceback' from 'D:\\Python39\\lib\\traceback.py'>

TypeError: loguru_print_exception() missing 1 required positional argument: 'chain'


During handling of the above exception, another exception occurred:


Traceback (most recent call last):

> File "E:\Code\QQWechat\graia_framework\sakura_ariadne\main.py", line 65, in <module>
    loop.run_until_complete(app.lifecycle())
    │    │                  │   └ <function Ariadne.lifecycle at 0x0000020E54AF5AF0>
    │    │                  └ <graia.ariadne.app.Ariadne object at 0x0000020E55507820>
    │    └ <function BaseEventLoop.run_until_complete at 0x0000020E532541F0>
    └ <ProactorEventLoop running=False closed=False debug=False>

  File "D:\Python39\lib\asyncio\base_events.py", line 629, in run_until_complete
    self.run_forever()
    │    └ <function ProactorEventLoop.run_forever at 0x0000020E5330FEE0>
    └ <ProactorEventLoop running=False closed=False debug=False>

  File "D:\Python39\lib\asyncio\windows_events.py", line 316, in run_forever
    super().run_forever()

  File "D:\Python39\lib\asyncio\base_events.py", line 596, in run_forever
    self._run_once()
    │    └ <function BaseEventLoop._run_once at 0x0000020E53255CA0>
    └ <ProactorEventLoop running=False closed=False debug=False>

  File "D:\Python39\lib\asyncio\base_events.py", line 1890, in _run_once
    handle._run()
    │      └ <function Handle._run at 0x0000020E531E6940>
    └ <Handle _ProactorBasePipeTransport._call_connection_lost(None)>

  File "D:\Python39\lib\asyncio\events.py", line 94, in _run
    self._loop.call_exception_handler(context)
    │    │                            └ {'message': 'Exception in callback _ProactorBasePipeTransport._call_connection_lost(None)', 'exception': OSError(10038, '在一个非...
    │    └ <member '_loop' of 'Handle' objects>
    └ <Handle _ProactorBasePipeTransport._call_connection_lost(None)>

  File "D:\Python39\lib\asyncio\base_events.py", line 1771, in call_exception_handler
    logger.error('Exception in default exception handler',
    │      └ <function Logger.error at 0x0000020E516E6940>
    └ <Logger asyncio (WARNING)>

  File "D:\Python39\lib\logging\__init__.py", line 1475, in error
    self._log(ERROR, msg, args, **kwargs)
    │    │    │      │    │       └ {'exc_info': True}
    │    │    │      │    └ ()
    │    │    │      └ 'Exception in default exception handler'
    │    │    └ 40
    │    └ <function Logger._log at 0x0000020E516E6CA0>
    └ <Logger asyncio (WARNING)>
  File "D:\Python39\lib\logging\__init__.py", line 1091, in emit
    self.handleError(record)
    │    │           └ <LogRecord: asyncio, 40, D:\Python39\lib\asyncio\base_events.py, 1771, "Exception in default exception handler">
    │    └ <function Handler.handleError at 0x0000020E516DF670>
    └ <_StderrHandler <stderr> (WARNING)>

  File "D:\Python39\lib\logging\__init__.py", line 1005, in handleError
    traceback.print_exception(t, v, tb, None, sys.stderr)
    │         │                               │   └ <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>
    │         │                               └ <module 'sys' (built-in)>
    │         └ <function loguru_print_exception at 0x0000020E53D431F0>
    └ <module 'traceback' from 'D:\\Python39\\lib\\traceback.py'>

TypeError: loguru_print_exception() missing 1 required positional argument: 'chain'

如何复现
等待后续补充

预期行为
你希望如何更改/原本应该是怎样的。

使用环境:

  • 系统: win11
  • MAH 版本: 2.3.1
  • Ariadne 版本:0.3.9
  • Python 版本:3.9.6
  • 其他 Graia 库版本:
  • 其他 有关 库版本:

日志/截图
将任何有关的日志/截图放到这里(控制台输出/MAH输出/...)

Add Issue/PR templates

  • 使用中遇到的问题
  • 发生了奇怪的异常
  • 行为不符合预期
  • 文档问题
  • (PR)新的 API/util

[Feature] 连接 MAH 失败达到一定次数时自动退出

使用场景.
无人值守且 MAH 挂了,同时 loguru 会记录 log 到日志文件时,可以防止 log 文件无限增大

你想要的解决方案
连接 MAH 失败或者 Adapter 异常停止达到一定次数时自动退出

是否已有相关实现
母鸡

其他内容
最好能允许在初始化 Ariadne 时传入参数改变自动退出的阈值

[Bug] 调用过被 cpu_bound 装饰过的函数后退出时报错

问题
调用过被 cpu_bound 装饰过的函数后退出时报错

如何复现

@cpu_bound
def abc():
    return 1


@channel.use(
    ListenerSchema(
        listening_events=[GroupMessage],
    )
)
async def main():
    i = await abc()
    print(i)

将上面的代码作为 Saya 插件加载,正常启动 Ariadne 并等待启动完成后按下 ctrl+c

  • 0.4.9 上在按下 ctrl+c 之后立刻出现: Process ForkProcess-1:KeyboardInterrupt,详细报错见 Pastebin
  • 2021.12.10.3 上在按下 ctrl+c 之后立刻出现 Process ForkProcess-1:

预期行为
两种都不报错

使用环境:

  • 系统: Linux Hostname 5.10.0-9-amd64 #1 SMP Debian 5.10.70-1 (2021-09-30) x86_64 GNU/Linux Debian 11.1
  • MAH 版本: 2.3.3
  • Python 版本: 3.10.1
  • Broadcast 版本: 0.14.4
  • Scheduler 版本: 0.0.6
  • Saya 版本: 0.0.13
  • 其他 有关 库版本:

日志/截图
Pastebin

[Bug] 调用 ariadne.app.Ariadne.uploadImage() 出错

问题
在尝试读取本地图片并上传时,调用 ariadne.app.Ariadne.uploadImage() 出错,错误信息为

TypeError: Only io.IOBase, multidict and (name, file) pairs allowed, use .add_field() for passing more complex parameters, got 'sessionKey'

该错误信息可能与源代码中的注释相矛盾

    @app_ctx_manager
    async def uploadImage(self, data: bytes, method: UploadMethod) -> "Image":
        """上传一张图片到远端服务器, 需要提供: 图片的原始数据(bytes), 图片的上传类型.
        Args:
            image_bytes (bytes): 图片的原始数据
            method (UploadMethod): 图片的上传类型
        Returns:
            Image: 生成的图片消息元素
        """
        from .message.element import Image

尝试使用 io.BytesIO.getvalue() 与 io.FileIO.read() 生成 bytes 均报该错误,尝试直接传入 io.BytesIO、io.FileIO、io.IOBase 仍均报该错误。
不知道是我的理解有问题还是打开方式不对,或者说bytes的格式不对……叨扰还请见谅

如何复现
在任意 listener 中调用 Ariadne.uploadImage() 并触发事件

预期行为
预期能够正常上传图片,并返回Image。如果可以的话,希望能在文档中简要提供示例

使用环境:

  • 系统: win11 21H2
  • MAH 版本: 2.3.3
  • Ariadne 版本: 0.4.8
  • Python 版本: 3.8.8
  • 其他 Graia 库版本:
    • Broadcast 0.14.4
    • Scheduler 0.0.4
    • Saya 0.0.13
  • 其他 有关 库版本:
    • aiohttp 3.7.4.post0

日志/截图
MAH在报错时无其它显示
QQ截图20211206014930
Python运行日志
QQ截图20211206012328
result['img'] 为 uploadImage() 的第一个输入参数,pycharm显示类型为bytes
QQ截图20211206012118

[Bug]KeybroadInterrupt退出时会出现段错误

问题
KeybroadInterrupt退出时会出现段错误

如何复现
开完就Ctrl + C

预期行为
没段错误

使用环境:

  • 系统:
  • MAH 版本: 2.4.0
  • Ariadne 版本: 0.4.9
  • Python 版本: 3.9
  • 其他 Graia 库版本:
  • 其他 有关 库版本:

日志/截图
将任何有关的日志/截图放到这里(控制台输出/MAH 输出/...)
使用faulthandler输出的报错
image

[Bug]发送群消息时若包含At元素则会出现异常

问题
发送群消息时若包含At元素则会出现异常,经调试应该是生成data时某些Graia的元素没有删除导致对MAH API的调用失败

如何复现

 @bcc.receiver(GroupMessage)
    async def reply(app: Ariadne, chain: MessageChain, group: Group, member: Member):
        if chain.asDisplay() == "Hi!":
            await app.sendGroupMessage(group, MessageChain.create([At(member.id), Plain("Hello World!")]))

预期行为
发送的消息包含At元素

使用环境:

  • 系统: Windows 10 专业版
  • MAH 版本: v2.3.3
  • Ariadne 版本:0.3.3.2
  • Python 版本:3.10
  • 其他 Graia 库版本:graia-broadcast 0.13.1 graia-saya 0.0.13
  • 其他 有关 库版本:默认版本

日志/截图
image
image

[Bug] 接受到的消息链不含有图片

问题
接受到的消息链不含有图片

例1 收到一条图片消息,其在Mirai的log中显示为
2021-11-03 14:53:44 V/Bot.xxxxxxxxx: [群名称(xxxxxxxxx)] Red_lnn(xxxxxxxxx) -> [mirai:image:{B341B788-1D4F-78C6-F77B-9709115D3D47}.jpg]

而bot得到的为

__root__=[Source(type='Source', id=1307659, time=datetime.datetime(2021, 11, 3, 6, 53, 45, tzinfo=datetime.timezone.utc))]

在另一机器上运行的旧版(0.19.2)的Graia Application得到的则是

__root__=(Source(id=1307659, time=datetime.datetime(2021, 11, 3, 6, 53, 45, tzinfo=datetime.timezone.utc)), Image(imageId='{B341B788-1D4F-78C6-F77B-9709115D3D47}.jpg', url='http://gchat.qpic.cn/gchatpic_new/xxxxxxxxx/726324810-2401023676-B341B7881D4F78C6F77B9709115D3D47/0?term=2', path=None, type=<ImageType.Unknown: 'Unknown'>))
例2 收到一条含有文本、At、图片的消息,其在Mirai的log中显示为
2021-11-03 15:04:37 V/Bot.xxxxxxxxx: [群名称(xxxxxxxxx)] Red_lnn(xxxxxxxxx) -> [mirai:at:xxxxxxxxx] 123456[mirai:image:{B341B788-1D4F-78C6-F77B-9709115D3D47}.jpg]789

而bot得到的为

__root__=[Source(type='Source', id=1307663, time=datetime.datetime(2021, 11, 3, 7, 4, 39, tzinfo=datetime.timezone.utc)), At(type='At', target=xxxxxxxxx, display=''), Plain(type='Plain', text=' 123456'), Plain(type='Plain', text='789')]

在另一机器上运行的旧版(0.19.2)的Graia Application得到的则是

__root__=(Source(id=1307663, time=datetime.datetime(2021, 11, 3, 7, 4, 39, tzinfo=datetime.timezone.utc)), At(type='At', target=xxxxxxxxx, display=''), Plain(type='Plain', text=' 123456'), Image(imageId='{B341B788-1D4F-78C6-F77B-9709115D3D47}.jpg', url='http://gchat.qpic.cn/gchatpic_new/xxxxxxxxx/726324810-3206812777-B341B7881D4F78C6F77B9709115D3D47/0?term=2', path=None, type=<ImageType.Unknown: 'Unknown'>), Plain(type='Plain', text='789'))

上面例子中包含旧版的Graia Application的信息,但由于没有升级到最新Graia Application,因此MAH版本为1.12.0,不清楚消息链不完整是否为MAH的问题

使用 mirai-console-loader 启动 mirai,不清楚如何获得MAH的输出

如何复现

@bcc.receiver('GroupMessage')
async def group_handler(chain: MessageChain):
   print(chain)


@bcc.receiver('FriendMessage')
async def friend_handler(chain: MessageChain):
   print(chain)

预期行为
与上面例1例2中的旧版的Graia Application获取到的消息链差不多,消息链中应含有Image对象

使用环境:

  • 系统: Windows 11 22000.282
  • MAH 版本: 2.3.3
  • Ariadne 版本: 0.3.4
  • Python 版本: 3.10.0
  • 其他 Graia 库版本: graia-broadcast==0.13.1
  • 其他 有关 库版本: pydantic==1.8.2
  • mirai 版本: mirai-console-2.8.0-RC mirai-console-terminal-2.8.0-RC mirai-core-all-2.8.0-RC

日志/截图
将任何有关的日志/截图放到这里(控制台输出/MAH输出/...)

见上面的例子

  • 例1消息在QQ客户端上看起来的样子

    image

  • 例2消息在QQ客户端上看起来的样子

    image

[Feature] Better import structure

使用场景
更方便的导入

你想要的解决方案

graia.ariadne.entry
graia.ariadne.entry.message
graia.ariadne.entry.event

是否已有相关实现
graia.application.entry

[Bug] `Queue.get` 任务退出时没被 `await`

问题 & 如何复现

使用 app.launch_blocking() 启动 Ariadne,不加载任何 Saya 插件,启动 Ariadne,待 Ariadne 启动完成后按下 ctrl+c,待 Ariadne 退出时报 RuntimeError: Event loop is closed

2021-12-11 20:48:14.840 | INFO     | graia.ariadne.app:launch:1298 - Application launched with 0.031s
2021-12-11 20:48:14.844 | DEBUG    | graia.ariadne.adapter:fetch_cycle:396 - websocket: received pong
^C2021-12-11 20:48:15.846 | DEBUG    | graia.ariadne.app:daemon:1242 - Ariadne daemon stopped.
2021-12-11 20:48:15.846 | INFO     | graia.ariadne.app:daemon:1247 - Stopping Ariadne...
2021-12-11 20:48:16.046 | DEBUG    | graia.ariadne.adapter:fetch_cycle:406 - websocket: ping task complete
2021-12-11 20:48:16.047 | DEBUG    | graia.ariadne.adapter:ws_ping:313 - websocket: pinger exit
2021-12-11 20:48:16.047 | INFO     | graia.ariadne.adapter:fetch_cycle:407 - websocket: disconnected
2021-12-11 20:48:16.048 | INFO     | graia.ariadne.app:daemon:1263 - Stopped Ariadne.
Exception ignored in: <coroutine object Queue.get at 0x7ffa476cba70>
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/asyncio/queues.py", line 161, in get
  File "/usr/local/lib/python3.10/asyncio/base_events.py", line 745, in call_soon
  File "/usr/local/lib/python3.10/asyncio/base_events.py", line 510, in _check_closed
RuntimeError: Event loop is closed

预期行为

不报错

使用环境:

  • 系统: Linux Hostname 5.10.0-9-amd64 #1 SMP Debian 5.10.70-1 (2021-09-30) x86_64 GNU/Linux Debian 11.1
  • MAH 版本: 2.3.3
  • Python 版本: 3.10.1
  • Ariadne 版本: 0.4.92021.12.10.3
  • Broadcast 版本: 0.14.4
  • Scheduler 版本: 0.0.6
  • Saya 版本: 0.0.13
  • 其他 有关 库版本:

[Bug]当以极快的速度于QQ客服端发送任意消息时会控制台会无限打印消息

问题
当以极快的速度于QQ客服端发送任意消息时会控制台会无限打印消息,且永不停止

如何复现
在QQ客服端快速、连续打相同字符(大约1s内在QQ客服端发送4次相同消息就可以触发了),使用的是Github该项目上面的示例代码

预期行为
仅显示该发送用户发送的内容

使用环境:

  • 系统:Windows 10专业版
  • MAH 版本:v2.3.3
  • Ariadne 版本:graia-ariadne version: 0.4.7
  • Python 版本:3.10
  • 其他 Graia 库版本:graia-broadcast version: 0.14.3
  • 其他 有关 库版本:mirai2.8.0RC/2.9.0-M1/2.8.2均可复现

日志/截图
将任何有关的日志/截图放到这里(控制台输出/MAH 输出/...)
image
从开始触发bug到人工介入结束程序期间QQ客服端总消息数
image
Mirai控制台输出(仅节选了1s内的一小部分输出,因为余下的输出也是这样的)(诡异的是发信人和收信人是一个QQ号)
image
控制台输出(诡异的是发信人和收信人是一个QQ号)

[Feature] 新消息链处理器

使用场景
Message Chain Parse

你想要的解决方案
argparse like API with enhanced function

是否已有相关实现
Literature, Kanata

[Bug] Adapter 无报错无限重启

使用中遇到的问题

Adapter 无报错无限重启
(经检查是个人问题,误打误撞发现了日志输出信息不够的另一个潜在问题,感谢 BlueGlassBlock 耐心指导)

运行环境

  • Windows 11 (22000.282)
  • Python 3.10.0 x64

依赖版本

  • aiohttp 3.7.4.post0
  • graia-ariadne 0.2.2
  • graia-broadcast 0.13.1
  • pydantic 1.8.2

所用的代码

import asyncio

from graia.ariadne.adapter import DefaultAdapter
from graia.ariadne.app import Ariadne
from graia.ariadne.message.chain import MessageChain
from graia.ariadne.message.element import Plain
from graia.ariadne.model import Friend, MiraiSession
from graia.broadcast import Broadcast

loop = asyncio.new_event_loop()

bcc = Broadcast(loop=loop)
app = Ariadne(
        broadcast=bcc,
        adapter=DefaultAdapter(
                bcc,
                MiraiSession(
                        host='http://localhost:8080',  # noqa # 填入 httpapi 服务运行的地址
                        account=********,  # 你的机器人的 qq 号
                        verify_key='********'  # 填入 verifyKey
                ),
        ),
)


@bcc.receiver("FriendMessage")
async def friend_message_listener(app: Ariadne, friend: Friend):
    await app.sendFriendMessage(friend, MessageChain.create([Plain("Hello, World!")]))


try:
    loop.run_until_complete(app.lifecycle())
except KeyboardInterrupt:
    loop.run_until_complete(app.stop())

控制台输出

此处为手动结束,不结束则一直重复下去

image

[Enhancement] ParamMatch and improved Sparkle

sp = Twilight(
    Sparkle([FullMatch("lp"), FullMatch("user"), ParamMatch(), FullMatch("set"), ParamMatch()])
).generate(MessageChain.create("lp user perm set 'DENIED -> NOLOGIN'"))
>>> debug(sp.get_match(ParamMatch))
[
        ParamMatch(
            matched=True,
            result=MessageChain(
                [
                    Plain(
                        text='perm',
                    ),
                ],
            ),
            pattern=...
        ),
        ParamMatch(
            matched=True,
            result=MessageChain(
                [
                    Plain(
                        text="'DENIED -> NOLOGIN'",
                    ),
                ],
            ),
            pattern=...
        ),
] (list) len=2
>>> debug(sp[ParamMatch, 0])

ParamMatch(
        matched=True,
        result=MessageChain(
            [
                Plain(
                    text='perm',
                ),
            ],
        ),
        pattern=...
) (ParamMatch)

[Feature] 更细粒度的生命周期

使用场景
ariadne.stop 后先停止接收事件, 等待事件分发完毕, 再实际停止实例.

你想要的解决方案
ariadne.running 替换为 ariadne.status 并支持更多状态

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.