mirror of
https://github.com/chatmail/core.git
synced 2026-05-09 09:56:31 +03:00
add Client.run_until()
This commit is contained in:
@@ -1,6 +1,17 @@
|
|||||||
"""Event loop implementations offering high level event handling/hooking."""
|
"""Event loop implementations offering high level event handling/hooking."""
|
||||||
|
import inspect
|
||||||
import logging
|
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
|
from deltachat_rpc_client.account import Account
|
||||||
|
|
||||||
@@ -56,6 +67,18 @@ class Client:
|
|||||||
self.logger.debug("Account configured")
|
self.logger.debug("Account configured")
|
||||||
|
|
||||||
async def run_forever(self) -> None:
|
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...")
|
self.logger.debug("Listening to incoming events...")
|
||||||
if await self.is_configured():
|
if await self.is_configured():
|
||||||
await self.account.start_io()
|
await self.account.start_io()
|
||||||
@@ -68,6 +91,12 @@ class Client:
|
|||||||
if event.type == EventType.INCOMING_MSG:
|
if event.type == EventType.INCOMING_MSG:
|
||||||
await self._process_messages()
|
await self._process_messages()
|
||||||
|
|
||||||
|
stop = func(event)
|
||||||
|
if inspect.isawaitable(stop):
|
||||||
|
stop = await stop
|
||||||
|
if stop:
|
||||||
|
return event
|
||||||
|
|
||||||
async def _on_event(
|
async def _on_event(
|
||||||
self, event: AttrDict, filter_type: Type[EventFilter] = RawEvent
|
self, event: AttrDict, filter_type: Type[EventFilter] = RawEvent
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from typing import AsyncGenerator, List
|
from typing import AsyncGenerator, List, Optional
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import pytest_asyncio
|
import pytest_asyncio
|
||||||
|
|
||||||
from .account import Account
|
from . import Account, AttrDict, Bot, Client, DeltaChat, EventType, Message
|
||||||
from .client import Bot
|
|
||||||
from .deltachat import DeltaChat
|
|
||||||
from .rpc import Rpc
|
from .rpc import Rpc
|
||||||
|
|
||||||
|
|
||||||
@@ -51,6 +49,46 @@ class ACFactory:
|
|||||||
await account.start_io()
|
await account.start_io()
|
||||||
return accounts
|
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
|
@pytest_asyncio.fixture
|
||||||
async def rpc(tmp_path) -> AsyncGenerator:
|
async def rpc(tmp_path) -> AsyncGenerator:
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from deltachat_rpc_client import AttrDict, EventType, events
|
from deltachat_rpc_client import EventType, events
|
||||||
from deltachat_rpc_client.rpc import JsonRpcError
|
from deltachat_rpc_client.rpc import JsonRpcError
|
||||||
|
|
||||||
|
|
||||||
@@ -216,40 +218,46 @@ async def test_message(acfactory) -> None:
|
|||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_bot(acfactory) -> None:
|
async def test_bot(acfactory) -> None:
|
||||||
async def callback(e):
|
def track(key):
|
||||||
res.append(e)
|
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()
|
bot = await acfactory.new_configured_bot()
|
||||||
|
|
||||||
assert await bot.is_configured()
|
assert await bot.is_configured()
|
||||||
assert await bot.account.get_config("bot") == "1"
|
assert await bot.account.get_config("bot") == "1"
|
||||||
|
|
||||||
bot.add_hook(callback, events.RawEvent(EventType.INFO))
|
hook = track("msg_id"), events.RawEvent(EventType.INCOMING_MSG)
|
||||||
info_event = AttrDict(account=bot.account, type=EventType.INFO, msg="info")
|
bot.add_hook(*hook)
|
||||||
warn_event = AttrDict(account=bot.account, type=EventType.WARNING, msg="warning")
|
event = await acfactory.process_message(
|
||||||
await bot._on_event(info_event)
|
from_account=user, to_client=bot, text="Hello!"
|
||||||
await bot._on_event(warn_event)
|
)
|
||||||
assert info_event in res
|
mock.hook.assert_called_once_with(event.id)
|
||||||
assert warn_event not in res
|
bot.remove_hook(*hook)
|
||||||
assert len(res) == 1
|
|
||||||
|
|
||||||
res = []
|
mock.hook.reset_mock()
|
||||||
bot.add_hook(callback, events.NewMessage(r"hello"))
|
hook = track("id"), events.NewMessage(r"hello")
|
||||||
bot.add_hook(callback, events.NewMessage(command="/help"))
|
bot.add_hook(*hook)
|
||||||
snapshot1 = AttrDict(text="hello", command=None)
|
bot.add_hook(track("id"), events.NewMessage(command="/help"))
|
||||||
snapshot2 = AttrDict(text="hello, world", command=None)
|
event = await acfactory.process_message(
|
||||||
snapshot3 = AttrDict(text="hey!", command=None)
|
from_account=user, to_client=bot, text="hello"
|
||||||
for snapshot in [snapshot1, snapshot2, snapshot3]:
|
)
|
||||||
await bot._on_event(snapshot, events.NewMessage)
|
mock.hook.assert_called_with(event.id)
|
||||||
assert len(res) == 2
|
event = await acfactory.process_message(
|
||||||
assert snapshot1 in res
|
from_account=user, to_client=bot, text="hello!"
|
||||||
assert snapshot2 in res
|
)
|
||||||
assert snapshot3 not in res
|
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 = []
|
mock.hook.reset_mock()
|
||||||
bot.remove_hook(callback, events.NewMessage(r"hello"))
|
await acfactory.process_message(from_account=user, to_client=bot, text="hello")
|
||||||
snapshot4 = AttrDict(command="/help")
|
event = await acfactory.process_message(
|
||||||
await bot._on_event(snapshot, events.NewMessage)
|
from_account=user, to_client=bot, text="/help"
|
||||||
await bot._on_event(snapshot4, events.NewMessage)
|
)
|
||||||
assert len(res) == 1
|
mock.hook.assert_called_once_with(event.id)
|
||||||
assert snapshot4 in res
|
|
||||||
|
|||||||
Reference in New Issue
Block a user