mirror of
https://github.com/chatmail/core.git
synced 2026-04-22 16:06:30 +03:00
add Client.run_until()
This commit is contained in:
@@ -1,6 +1,17 @@
|
||||
"""Event loop implementations offering high level event handling/hooking."""
|
||||
import inspect
|
||||
import logging
|
||||
from typing import Callable, Dict, Iterable, Optional, Set, Tuple, Type, Union
|
||||
from typing import (
|
||||
Callable,
|
||||
Coroutine,
|
||||
Dict,
|
||||
Iterable,
|
||||
Optional,
|
||||
Set,
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
)
|
||||
|
||||
from deltachat_rpc_client.account import Account
|
||||
|
||||
@@ -56,6 +67,18 @@ class Client:
|
||||
self.logger.debug("Account configured")
|
||||
|
||||
async def run_forever(self) -> None:
|
||||
"""Process events forever."""
|
||||
await self.run_until(lambda _: False)
|
||||
|
||||
async def run_until(
|
||||
self, func: Callable[[AttrDict], Union[bool, Coroutine]]
|
||||
) -> AttrDict:
|
||||
"""Process events until the given callable evaluates to True.
|
||||
|
||||
The callable should accept an AttrDict object representing the
|
||||
last processed event. The event is returned when the callable
|
||||
evaluates to True.
|
||||
"""
|
||||
self.logger.debug("Listening to incoming events...")
|
||||
if await self.is_configured():
|
||||
await self.account.start_io()
|
||||
@@ -68,6 +91,12 @@ class Client:
|
||||
if event.type == EventType.INCOMING_MSG:
|
||||
await self._process_messages()
|
||||
|
||||
stop = func(event)
|
||||
if inspect.isawaitable(stop):
|
||||
stop = await stop
|
||||
if stop:
|
||||
return event
|
||||
|
||||
async def _on_event(
|
||||
self, event: AttrDict, filter_type: Type[EventFilter] = RawEvent
|
||||
) -> None:
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import json
|
||||
import os
|
||||
from typing import AsyncGenerator, List
|
||||
from typing import AsyncGenerator, List, Optional
|
||||
|
||||
import aiohttp
|
||||
import pytest_asyncio
|
||||
|
||||
from .account import Account
|
||||
from .client import Bot
|
||||
from .deltachat import DeltaChat
|
||||
from . import Account, AttrDict, Bot, Client, DeltaChat, EventType, Message
|
||||
from .rpc import Rpc
|
||||
|
||||
|
||||
@@ -51,6 +49,46 @@ class ACFactory:
|
||||
await account.start_io()
|
||||
return accounts
|
||||
|
||||
async def send_message(
|
||||
self,
|
||||
to_account: Account,
|
||||
from_account: Optional[Account] = None,
|
||||
text: Optional[str] = None,
|
||||
file: Optional[str] = None,
|
||||
group: Optional[str] = None,
|
||||
) -> Message:
|
||||
if not from_account:
|
||||
from_account = (await self.get_online_accounts(1))[0]
|
||||
to_contact = await from_account.create_contact(
|
||||
await to_account.get_config("addr")
|
||||
)
|
||||
if group:
|
||||
to_chat = await from_account.create_group(group)
|
||||
await to_chat.add_contact(to_contact)
|
||||
else:
|
||||
to_chat = await to_contact.create_chat()
|
||||
return await to_chat.send_message(text=text, file=file)
|
||||
|
||||
async def process_message(
|
||||
self,
|
||||
to_client: Client,
|
||||
from_account: Optional[Account] = None,
|
||||
text: Optional[str] = None,
|
||||
file: Optional[str] = None,
|
||||
group: Optional[str] = None,
|
||||
) -> AttrDict:
|
||||
await self.send_message(
|
||||
to_account=to_client.account,
|
||||
from_account=from_account,
|
||||
text=text,
|
||||
file=file,
|
||||
group=group,
|
||||
)
|
||||
|
||||
event = await to_client.run_until(lambda e: e.type == EventType.INCOMING_MSG)
|
||||
msg = await to_client.account.get_message_by_id(event.msg_id)
|
||||
return await msg.get_snapshot()
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def rpc(tmp_path) -> AsyncGenerator:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from deltachat_rpc_client import AttrDict, EventType, events
|
||||
from deltachat_rpc_client import EventType, events
|
||||
from deltachat_rpc_client.rpc import JsonRpcError
|
||||
|
||||
|
||||
@@ -216,40 +218,46 @@ async def test_message(acfactory) -> None:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bot(acfactory) -> None:
|
||||
async def callback(e):
|
||||
res.append(e)
|
||||
def track(key):
|
||||
async def wrapper(e):
|
||||
mock.hook(e[key])
|
||||
|
||||
res = []
|
||||
return wrapper
|
||||
|
||||
mock = MagicMock()
|
||||
user = (await acfactory.get_online_accounts(1))[0]
|
||||
bot = await acfactory.new_configured_bot()
|
||||
|
||||
assert await bot.is_configured()
|
||||
assert await bot.account.get_config("bot") == "1"
|
||||
|
||||
bot.add_hook(callback, events.RawEvent(EventType.INFO))
|
||||
info_event = AttrDict(account=bot.account, type=EventType.INFO, msg="info")
|
||||
warn_event = AttrDict(account=bot.account, type=EventType.WARNING, msg="warning")
|
||||
await bot._on_event(info_event)
|
||||
await bot._on_event(warn_event)
|
||||
assert info_event in res
|
||||
assert warn_event not in res
|
||||
assert len(res) == 1
|
||||
hook = track("msg_id"), events.RawEvent(EventType.INCOMING_MSG)
|
||||
bot.add_hook(*hook)
|
||||
event = await acfactory.process_message(
|
||||
from_account=user, to_client=bot, text="Hello!"
|
||||
)
|
||||
mock.hook.assert_called_once_with(event.id)
|
||||
bot.remove_hook(*hook)
|
||||
|
||||
res = []
|
||||
bot.add_hook(callback, events.NewMessage(r"hello"))
|
||||
bot.add_hook(callback, events.NewMessage(command="/help"))
|
||||
snapshot1 = AttrDict(text="hello", command=None)
|
||||
snapshot2 = AttrDict(text="hello, world", command=None)
|
||||
snapshot3 = AttrDict(text="hey!", command=None)
|
||||
for snapshot in [snapshot1, snapshot2, snapshot3]:
|
||||
await bot._on_event(snapshot, events.NewMessage)
|
||||
assert len(res) == 2
|
||||
assert snapshot1 in res
|
||||
assert snapshot2 in res
|
||||
assert snapshot3 not in res
|
||||
mock.hook.reset_mock()
|
||||
hook = track("id"), events.NewMessage(r"hello")
|
||||
bot.add_hook(*hook)
|
||||
bot.add_hook(track("id"), events.NewMessage(command="/help"))
|
||||
event = await acfactory.process_message(
|
||||
from_account=user, to_client=bot, text="hello"
|
||||
)
|
||||
mock.hook.assert_called_with(event.id)
|
||||
event = await acfactory.process_message(
|
||||
from_account=user, to_client=bot, text="hello!"
|
||||
)
|
||||
mock.hook.assert_called_with(event.id)
|
||||
await acfactory.process_message(from_account=user, to_client=bot, text="hey!")
|
||||
assert len(mock.hook.mock_calls) == 2
|
||||
bot.remove_hook(*hook)
|
||||
|
||||
res = []
|
||||
bot.remove_hook(callback, events.NewMessage(r"hello"))
|
||||
snapshot4 = AttrDict(command="/help")
|
||||
await bot._on_event(snapshot, events.NewMessage)
|
||||
await bot._on_event(snapshot4, events.NewMessage)
|
||||
assert len(res) == 1
|
||||
assert snapshot4 in res
|
||||
mock.hook.reset_mock()
|
||||
await acfactory.process_message(from_account=user, to_client=bot, text="hello")
|
||||
event = await acfactory.process_message(
|
||||
from_account=user, to_client=bot, text="/help"
|
||||
)
|
||||
mock.hook.assert_called_once_with(event.id)
|
||||
|
||||
Reference in New Issue
Block a user