matrix-commander icon indicating copy to clipboard operation
matrix-commander copied to clipboard

Feature Request: Send direct message (DM) without a prior room name

Open toushin-taishi opened this issue 3 years ago • 14 comments

Hello. Is it possible for matrix-commander to send DMs (direct message) to a matrix account without a prior room name? I am thinking of using matrix-commander as a notification medium but cannot entirely automate the process if a room name is needed on every DM.

Kind regards

toushin-taishi avatar Dec 02 '21 05:12 toushin-taishi

I'm looking for this feature too. The matrix-nio library supports creating rooms without aliases, and also direct messaging rooms, but it doesn't look like it's implemented in m-c. I'm interested in adding support myself, but it will take a while as my Python is pretty shabby. I'm a Perl guy ;)

See https://matrix-nio.readthedocs.io/en/latest/nio.html#nio.Api.room_create and https://github.com/8go/matrix-commander/blob/7ab3fd9a0ef4eb19d882cb3701d2025b4d41b63a/matrix-commander.py#L1659

edwinsage avatar Apr 25 '22 00:04 edwinsage

Thank you both @toushin-taishi and @edwinsage for your input.

Question: In the Element client (say on Android, or Webpage), can one send a DM, i.e. a message to someone, without a room name? As far as I can tell Element always has a room name, even for what they call "People" in their GUI.

Usually the flow is: create a room, invite, join, send.

aliases have nothing to do with this, in my opinion. These are just secondary alternative names for rooms.

direct messaging rooms: as far as I understand these are rooms marked with an is_direct flag. Not much more. Please educate me if there is more I should know about the is_direct flag.

  • Can you please explain more how you envision this?
  • What would the command line options be?
  • What would the individual steps be?
  • How would that be implemented?
  • Does matrix-nio sample code for DM exist somewhere?

Keep in mind that matrix-commander wants to be stateless, no database to look up what the room id for sender-receiver X-Y.

if there is anyone else out there who knows how to do that, please :pray: comment!

As far as I know one cannot send to a person, one always sends to a room (direct room or not). So, mc always needs a room id. At a higher level, one can associate room id 1234... which is a room between person X and person Y to an alias. E.g. person X knows that the room with 1234... is the DM for him (X) to talk to Y. So, X can set up a shell variable Y="1234..." and then send a DM to Y by typing matrix-commander --room "$Y" -m "Hi there". That is a work-around available and used by many today.

One could think of this: mc queries all available rooms, queries all the members in these rooms and then determines if there is a room that only holds two members, one being the "you" and the other being the person you want to send to. If such a room is found then it is a DM-room or like a DM-room as it only has you and the receiver in it. Then send to this found room. This is most likely do-able, but many queries and most likely slow. Also, there could be many such rooms with only you and the receive in it, even multiple ones with the is_direct flag set. So, to which one of these rooms does mc send the message then?

Waiting and curious about your ideas, viewpoints, suggestions!

8go avatar May 25 '22 17:05 8go

This is another subject where I have made a personal patch on my fork. I assume the original issue is about needing to specify an alias when making a room, which can get in the way of generating rooms on the fly.

In my use case, users would "register" in one public room, and my bot would create and invite them to a private room to communicate directly. While I could have invented a system for generating room aliases randomly and then included checks for when room alias collisions happen, I found it simpler to modify MC to allow it to make rooms that do not have an alias, and changed it to output the room ID whenever it creates a room. It turns out the nio library already supports this and only requires making the room creation request without being given an alias, so the code change is minimal. I didn't make a pull request again as it didn't seem like a neat solution, but the changes worked for my needs. The two commits are here: https://github.com/edwinsage/matrix-commander/commit/db7c278bd015f910b17a9b2cd9628efdaea844ab https://github.com/edwinsage/matrix-commander/commit/8509f2b64be5a43f5876a0649a423032010573c1

This increases the risk of creating rooms that get "lost" as the only way to identify the room is on the output, rather than in your input, but presumably there is a way to list all rooms one is connected to (otherwise how would interactive matrix clients even work?).

edwinsage avatar May 26 '22 21:05 edwinsage

Question: In the Element client (say on Android, or Webpage), can one send a DM, i.e. a message to someone, without a room name? As far as I can tell Element always has a room name, even for what they call "People" in their GUI.

Hi @8go. In Element, one can use the command /msg <user-id> [<message>]. Element will automatically create a room if one does not exist between you and the <user-id>.

This was actually the inspiration for this feature request I guess.

toushin-taishi avatar May 27 '22 01:05 toushin-taishi

I've been trying to dig in to how this would work, but I'm still stuck at the moment. It looks like there may be a way to get a list of potential DM rooms by user: https://spec.matrix.org/v1.2/client-server-api/#mdirect But I'm not sure how that interface works or how the information is updated, as it appears to be stored in user data, not in the room itself? Maybe someone with more experience with the spec can make better sense of this.

edwinsage avatar May 28 '22 19:05 edwinsage

Apps with phone numbers like Signal and WhatsApp and Twitter support "DM" because there is makes sense. There is only one "you". These apps are person-based. You have exactly 1 account. (Generally speaking,)

Matrix is more "room"-based. Every person can have multiple "personas", so it is not so clear cut.

@toushin-taishi : Ok, that was useful input. Thank you. That sort of confirms one possibility. (As mentioned) One could go though all the rooms to see if a room exists with only this one other recipient. If one or more of such rooms exist, send to an arbitrary one. If no such room exists, send an invite to create room. Etc.

@edwinsage : Thanks for the link. It adds a bit of information. It also confirms that the "is_direct" flag is more of a hint, it does not enforce anything. It expresses a desire. This was my understanding and continues to be my understanding. But from that URL https://spec.matrix.org/v1.2/client-server-api/#mdirect I learned that at the Synapse level there should be an API call to request from the server the list of all rooms that are labelled "is_direct". I will have a look at matrix-nio to see if there is such an API call also in matrix-nio.

8go avatar May 31 '22 09:05 8go

Searches

I did a search of "direct" in matrix-nio documentation: https://matrix-nio.readthedocs.io/en/latest/search.html?q=direct&check_keywords=yes&area=default

Please correct me if I am wrong somewhere. I found only 2 slightly relevant hits of the term "direct".

https://matrix-nio.readthedocs.io/en/latest/nio.html?highlight=direct#module-nio.event_builders.direct_messages :: this is not appropriate, it allows sending to a specific device, but one must have the device ID, I don't think this is what a DM should do, a DM should send to all devices

https://matrix-nio.readthedocs.io/en/latest/examples.html?highlight=direct#manual-encryption-key-verification :: Big portions of this page are PRs from myself to matrix-nio. Just an irrelevant mention of This can be a direct message or room; Matrix treats them the same.

Then I searched: https://matrix-nio.readthedocs.io/en/latest/search.html?q=is_direct&check_keywords=yes&area=default#

I found what I expected: how to set the is_direct flag as a hint when you create a room. Nothing beyond that.

Conclusion

I reached the conclusion that matrix-nio does not have any API that would support anything related to "DM". Again, I would love for someone to tell me that I am wrong and that the API call is XYZ. So, if someone out there knows how to do a "DM" call in matrix-nio please do tell us.

That only leaves me with the idea of getting all rooms, all members of all these rooms to try to find a room that only has sender and receiver in it and nobody else. Take that room id and send the message there. Worth it? Please comment.

8go avatar May 31 '22 09:05 8go

@edwinsage and @toushin-taishi

Finally I implemented 2 membership options for rooms and room members.

Have a look at commit acb4bde

  --joined-rooms        Print the list of joined rooms. All rooms that you are
                        a member of will be printed, one room per line.
  --joined-members JOINED_MEMBERS [JOINED_MEMBERS ...]
                        Print the list of joined members for one or multiple
                        rooms. If you want to print the joined members of all
                        rooms that you are member of, then use the special
                        character '*'.

That gets us much closer to a DM.

8go avatar May 31 '22 17:05 8go

That only leaves me with the idea of getting all rooms, all members of all these rooms to try to find a room that only has sender and receiver in it and nobody else. Take that room id and send the message there. Worth it? Please comment.

I think if matrix-nio has a way to check whether the is_direct flag is set for a room, then it would make sense to add a polling feature to allow MC to find and use DM rooms. If not, then I think it makes more sense to leave this to a wrapper or other script (outside of this project) that creates its own DM rooms and tracks their existence itself. In that case, it would be helpful to add a feature that allows creating rooms with the is_direct flag to MC.

edwinsage avatar May 31 '22 18:05 edwinsage

https://matrix-nio.readthedocs.io/en/latest/nio.html?module-nio.rooms#module-nio.rooms

There is no API call to get is_direct flag.

But there is an API call for is_group https://matrix-nio.readthedocs.io/en/latest/nio.html?nio.rooms.MatrixRoom.is_group

It says: "Determine whether a room is an ad-hoc group (often a direct chat). A group is an unnamed room with no canonical alias."

Again, this is just a hint. No guarantee that this is actually a room between 2 people.

8go avatar May 31 '22 19:05 8go

DM is now done. See commit 40e3c87

It gets the rooms of the sender, then it gets the members of all these rooms, then it searches through this list to find a room that only has 2 members and them being sender and receiver. As name match 3 choices are handled: full user id, partial user id, display name.

Try it and report back if it works for you!

  • one can now specify a person (instead of a room to send to)
  • --message, --audio, etc. now work in conjunction with --user
  • --listen (some forms) now work in conjunction with --user
$ # Send to a specific user, DM, direct messaging, using full user id
$ matrix-commander -m "hi" --user '@myfriend:example.org'
$ # Send to a specific user, DM, direct messaging, using partial user id
$ # It will be assumed that user @myfriend is on same homeserver
$ matrix-commander -m "hi" --user '@myfriend'
$ # Send to a specific user, DM, direct messaging, using display name
$ # Careful! Display names might not be unique. Don't DM the wrong person!
$ # To double-check the display names do a --joined-members "*"
$ matrix-commander -m "hi" -u 'Joe'
$ # Send to multiple users
$ matrix-commander -m "hi" -u '@joe:example.org' '@jane:example.org'
$ # Send to multiple users, another way
$ matrix-commander -m "hi" -u '@joe:example.org' -u '@jane:example.org'

8go avatar Jun 01 '22 09:06 8go

Hi @8go, Thanks for the effort in implementing this request. I tested using the latest git and as the commit stated, it works if the bot and the recipient have an existing room.

Please tell me if i can be of any help in terms of testing this new feature.

toushin-taishi avatar Jun 07 '22 01:06 toushin-taishi

Thanks @toushin-taishi for the feedback, confirming that it is working for you. Great to hear.

My intention was to leave it as-is. The user is responsible for creating the room and sending invite through any means he wants, e.g. with Element or with matrix-commander --room-create ... and matrix-commander --room-invite ... .

I just saw that GitHub automatically replaced @user patterns in my copy-paste of the code. The above examples look weird, now fixed.

8go avatar Jun 07 '22 16:06 8go

DM messages only get set to a room and not to users outside room

matrix-commander -m "hi" --user '@bob' ERROR: matrix-commander: Room(s) were specified for a DM (direct messaging) send operation via --room. But no DM room was found for user '@bob'. Try setting up a room first via --room-create and --room-invite option. INFO: matrix-commander: No rooms are given. This should not happen. Maybe your DM rooms specified via --user were not found. This text message is being dropped and NOT sent.

TroyWilson1 avatar Sep 15 '22 22:09 TroyWilson1

@TroyWilson1 Please explain yourself by adding more detail. I am not sure what the issue is. The room will not be automatically created. You have to do that separately.

I think I get what you are trying to say: DM does not work if no room exists with this user. This is correct. A room with the user must exist, otherwise DM will not work. That is the way it works with matrix-commander.

No surprise, expected behavior.

8go avatar Oct 02 '22 15:10 8go

Closing issue. Reopen if need be.

8go avatar Oct 03 '22 20:10 8go