Skip to content

Commit

Permalink
Merge pull request #21 from chatbot-smooth/typing-notification
Browse files Browse the repository at this point in the history
Added typing notification feature
  • Loading branch information
bramenn committed Mar 29, 2023
2 parents dcbe17f + 2f50f1a commit 5a1e79e
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 8 deletions.
1 change: 1 addition & 0 deletions menuflow/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def do_update(self, helper: ConfigUpdateHelper) -> None:
copy("menuflow.timeouts.http_requests")
copy("menuflow.timeouts.middlewares")
copy("menuflow.email_servers")
copy("menuflow.typing_notification")
copy("server.hostname")
copy("server.port")
copy("server.public_url")
Expand Down
7 changes: 7 additions & 0 deletions menuflow/example-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ menuflow:
username: user2
password: pass2

# Do you want the menu to generate a typing notification event before sending messages to rooms?
# The range is related to the time duration of the write notification event.
typing_notification:
enable: true
start: 1
end: 3

server:
# The IP and port to listen to.
hostname: 0.0.0.0
Expand Down
38 changes: 38 additions & 0 deletions menuflow/nodes/base.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from __future__ import annotations

from abc import abstractmethod
from asyncio import create_task, sleep
from json import JSONDecodeError, dumps, loads
from logging import getLogger
from random import randrange
from typing import Dict, List

from aiohttp import ClientSession
from mautrix.client import Client as MatrixClient
from mautrix.types import MessageEventContent, RoomID
from mautrix.util.logging import TraceLogger

from ..config import Config
Expand Down Expand Up @@ -61,6 +64,41 @@ def init_cls(cls, config: Config, matrix_client: MatrixClient, default_variables
async def run(self):
pass

async def set_typing(self, room_id: RoomID):
"""It sets the typing notification for a random amount of time between 1 and 3 seconds
Parameters
----------
room_id : RoomID
The room ID of the room you want to send the typing notification to.
"""
start = self.config["menuflow.typing_notification.start"] or 1
end = self.config["menuflow.typing_notification.end"] or 3
typing_time = randrange(start, end)
await self.matrix_client.set_typing(room_id=room_id, timeout=typing_time)
await sleep(typing_time)

async def send_message(self, room_id: RoomID, content: MessageEventContent):
"""It sends a message to the room.
Parameters
----------
room_id : RoomID
The room ID of the room you want to send the message to.
content : MessageEventContent
The content of the message.
"""

async def send():
if self.config["menuflow.typing_notification.enable"]:
await self.set_typing(room_id=room_id)

await self.matrix_client.send_message(room_id=room_id, content=content)

create_task(send())

def render_data(self, data: Dict | List | str) -> Dict | List | str:
"""It takes a dictionary or list, converts it to a string,
and then uses Jinja to render the string
Expand Down
2 changes: 1 addition & 1 deletion menuflow/nodes/location.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async def run(self):
body=f"User Location geo:{self.longitude},{self.latitude} at {datetime.utcnow()}",
geo_uri=f"geo:{self.longitude},{self.latitude}",
)
await self.matrix_client.send_message(room_id=self.room.room_id, content=location_message)
await self.send_message(room_id=self.room.room_id, content=location_message)
await self.room.update_menu(
node_id=self.o_connection,
state=RoomState.END if not self.o_connection else None,
Expand Down
2 changes: 1 addition & 1 deletion menuflow/nodes/media.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ async def run(self):
media_message = await self.load_media()
self.media_cache[self.url] = media_message

await self.matrix_client.send_message(room_id=self.room.room_id, content=media_message)
await self.send_message(room_id=self.room.room_id, content=media_message)

await self.room.update_menu(
node_id=self.o_connection,
Expand Down
2 changes: 1 addition & 1 deletion menuflow/nodes/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ async def run(self):
formatted_body=markdown(self.text),
)

await self.matrix_client.send_message(room_id=self.room.room_id, content=msg_content)
await self.send_message(room_id=self.room.room_id, content=msg_content)

await self._update_node()
17 changes: 16 additions & 1 deletion test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,28 @@
from pytest_mock import MockerFixture

from menuflow import Flow, Room, Util
from menuflow.config import Config
from menuflow.nodes import Base, Input, Location, Message, Switch


@pytest_asyncio.fixture
async def flow() -> Flow:
async def config() -> Config:
_config = Config(
path="menuflow/example-config.yaml",
base_path="menuflow",
)
_config.load()
return _config


@pytest_asyncio.fixture
async def flow(config: Config) -> Flow:
flow = Flow(Util.flow_example().get("menu"))
flow.load()

for node in [Input, Location, Message, Switch]:
node.config = config

return flow


Expand Down
2 changes: 1 addition & 1 deletion test/test_nodes/test_location.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ def test_longitude_latitude(self, location: Location):
@pytest.mark.asyncio
async def test_run(self, location: Location, mocker: MockerFixture):
async_mock = AsyncMock()
mock_func = mocker.patch.object(Client, "send_message", side_effect=async_mock)
mock_func = mocker.patch.object(Location, "send_message", side_effect=async_mock)
await location.run()
assert mock_func.called == True
5 changes: 2 additions & 3 deletions test/test_nodes/test_message.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import nest_asyncio
import pytest
from asyncmock import AsyncMock
from mautrix.client import Client
from mautrix.types import MessageType
from pytest_mock import MockerFixture

Expand Down Expand Up @@ -39,9 +38,9 @@ async def test_update_node_to_end(self, message: Message):
assert message.room.node_id == ""
assert message.room.state == RoomState.END

@pytest.mark.asyncio
@pytest.mark.asyncio()
async def test_run(self, message: Message, mocker: MockerFixture):
async_mock = AsyncMock()
mock_func = mocker.patch.object(Client, "send_message", side_effect=async_mock)
mock_func = mocker.patch.object(Message, "send_message", side_effect=async_mock)
await message.run()
assert mock_func.called == True

0 comments on commit 5a1e79e

Please sign in to comment.