Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Set the DM flag on new DMs #6

Merged
merged 9 commits into from
Apr 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ python_requires = >= 3.7
[options.extras_require]
dev =
# for tests
matrix-synapse
matrix-synapse >= 1.57.0
tox
twisted
aiounittest
Expand Down
42 changes: 41 additions & 1 deletion synapse_auto_accept_invite/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from typing import Any, Dict, Optional
from typing import Any, Dict, List, Optional

import attr
from synapse.module_api import EventBase, ModuleApi

logger = logging.getLogger(__name__)
ACCOUNT_DATA_DIRECT_MESSAGE_LIST = "m.direct"


@attr.s(auto_attribs=True, frozen=True)
Expand Down Expand Up @@ -101,3 +102,42 @@ async def on_new_event(self, event: EventBase, *args: Any) -> None:
room_id=event.room_id,
new_membership="join",
)

if is_direct_message:
# Mark this room as a direct message!
await self._mark_room_as_direct_message(
event.state_key, event.sender, event.room_id
)

async def _mark_room_as_direct_message(
self, user_id: str, dm_user_id: str, room_id: str
) -> None:
"""
Marks a room (`room_id`) as a direct message with the counterparty `dm_user_id`
from the perspective of the user `user_id`.
"""

# This dict of User IDs to lists of Room IDs
dm_map: Dict[str, List[str]] = (
await self._api.account_data_manager.get_global(
user_id, ACCOUNT_DATA_DIRECT_MESSAGE_LIST
)
or {}
)

if dm_user_id not in dm_map:
dm_map[dm_user_id] = [room_id]
else:
if not isinstance(dm_map[dm_user_id], list):
# Don't mangle the data if we don't understand it.
logger.warning(
"Not marking room as DM for auto-accepted invitatation; dm_map[%r] not a list.",
dm_user_id,
)
return

dm_map[dm_user_id].append(room_id)

await self._api.account_data_manager.put_global(
user_id, ACCOUNT_DATA_DIRECT_MESSAGE_LIST, dm_map
)
12 changes: 8 additions & 4 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Any, Dict, Optional
from typing import Any, Dict, Optional, TypeVar
from unittest.mock import Mock

import attr
Expand Down Expand Up @@ -43,6 +43,13 @@ def membership(self) -> str:
return membership


T = TypeVar("T")


async def make_awaitable(value: T) -> T:
return value


def create_module(
config_override: Dict[str, Any] = {}, worker_name: Optional[str] = None
) -> InviteAutoAccepter:
Expand All @@ -54,9 +61,6 @@ def create_module(

# Python 3.6 doesn't support awaiting on a mock, so we make it return an awaitable
# value.
async def make_awaitable(result: Any) -> Any:
return result

module_api.update_room_membership.return_value = make_awaitable(None)
config = InviteAutoAccepter.parse_config(config_override)

Expand Down
40 changes: 39 additions & 1 deletion tests/test_example.py → tests/test_accept_invite.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import aiounittest

from synapse_auto_accept_invite import InviteAutoAccepter
from tests import MockEvent, create_module
from tests import MockEvent, create_module, make_awaitable


class InviteAutoAccepterTestCase(aiounittest.AsyncTestCase):
Expand Down Expand Up @@ -57,12 +57,30 @@ async def test_accept_invite(self) -> None:
async def test_accept_invite_direct_message(self) -> None:
"""Tests that receiving an invite for a local user makes the module attempt to
make the invitee join the room even if the invite is for a direct message room.
Moreover, check that the room is marked as a direct message in this case.
"""
invite = MockEvent(
sender=self.user_id,
state_key=self.invitee,
type="m.room.member",
content={"membership": "invite", "is_direct": True},
room_id="!the:room",
)

# We will mock out the account data get/put methods to check that the flags
# are properly set.
account_data_put: Mock = cast(
Mock, self.module._api.account_data_manager.put_global
)
account_data_put.return_value = make_awaitable(None)

account_data_get: Mock = cast(
Mock, self.module._api.account_data_manager.get_global
)
account_data_get.return_value = make_awaitable(
{
"@someone:random": ["!somewhere:random"],
}
)

# Stop mypy from complaining that we give on_new_event a MockEvent rather than an
Expand All @@ -78,6 +96,19 @@ async def test_accept_invite_direct_message(self) -> None:
new_membership="join",
)

account_data_get.assert_called_once_with(self.invitee, "m.direct")

# Check that the account data was correctly updated; notably that it doesn't
# overwrite the existing associations!
account_data_put.assert_called_once_with(
self.invitee,
"m.direct",
{
"@someone:random": ["!somewhere:random"],
self.user_id: ["!the:room"],
},
)

async def test_remote_user(self) -> None:
"""Tests that receiving an invite for a remote user does nothing."""
invite = MockEvent(
Expand Down Expand Up @@ -147,6 +178,13 @@ async def test_accept_invite_direct_message_if_only_enabled_for_direct_messages(
config_override={"accept_invites_only_for_direct_messages": True},
)

# Patch out the account data get and put methods with dummy awaitables.
account_data_put: Mock = cast(Mock, module._api.account_data_manager.put_global)
account_data_put.return_value = make_awaitable(None)

account_data_get: Mock = cast(Mock, module._api.account_data_manager.get_global)
account_data_get.return_value = make_awaitable({})

invite = MockEvent(
sender=self.user_id,
state_key=self.invitee,
Expand Down
12 changes: 0 additions & 12 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ usedevelop=true

extras = dev

deps =
# we need to run on Synapse develop for now until https://github.com/matrix-org/synapse/pull/11147
# ships in Synapse v1.47.0
# TODO: remove once 1.47.0 is released
git+https://github.com/matrix-org/synapse.git@develop#egg=matrix-synapse

commands =
python -m twisted.trial tests

Expand All @@ -39,11 +33,5 @@ commands =

extras = dev

deps =
# we need to run on Synapse develop for now until https://github.com/matrix-org/synapse/pull/11147
# ships in Synapse v1.47.0
# TODO: remove once 1.47.0 is released
git+https://github.com/matrix-org/synapse.git@develop#egg=matrix-synapse

commands =
mypy synapse_auto_accept_invite tests