-
Notifications
You must be signed in to change notification settings - Fork 121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DO NOT MERGE] add an option to use display names in chatrooms #28
base: olm-command
Are you sure you want to change the base?
Conversation
# TODO make this configurable | ||
if not short_name or short_name in self.displayed_nicks.values(): | ||
# Use the full user id, but don't include the @ | ||
nick = user_id[1:] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could not quite wrap my head around this if
branch.
Was this an workaround to remote ambiguity? I did not notice that this branch is ever executed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short name can be an empty string here if someone has a user id of the format "@:example.org", someone in Matrix HQ had such an user id.
Short name can already be in displayed_nicks if two people have the same user part of the user_id. For example "@alice.example1.org" and "@alice.example2.org".
So it seems that weechat's nicklist can support somehow addition of same nick multiple times, it returns different nick_ptr every time and you can use it to delete the nick, but it displays only one nick in the nicklist pane. I kinda have intention to find a way to disambiguate nicks in nicklist's pane but keep short displayname in rooms log using different colors to distinguish one from the other. While I'm trying to find approach to this I think PR is still reviewable since I don't think it's going to be changed much. |
# TODO make this configurable | ||
if not short_name or short_name in self.displayed_nicks.values(): | ||
# Use the full user id, but don't include the @ | ||
nick = user_id[1:] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short name can be an empty string here if someone has a user id of the format "@:example.org", someone in Matrix HQ had such an user id.
Short name can already be in displayed_nicks if two people have the same user part of the user_id. For example "@alice.example1.org" and "@alice.example2.org".
matrix/buffer.py
Outdated
@@ -227,6 +230,7 @@ class WeechatChannelBuffer(object): | |||
"kick": [SCRIPT_NAME + "_kick", "log4"], | |||
"invite": [SCRIPT_NAME + "_invite", "log4"], | |||
"topic": [SCRIPT_NAME + "_topic", "log3"], | |||
"change": [SCRIPT_NAME + "_change", "log4"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used the same tags that the irc plugin uses since some plugins can reuse some known tags, also for consistency sake.
The irc plugin uses irc_nick for nick changes.
@@ -491,13 +495,13 @@ def _message_tags(self, user, message_type): | |||
|
|||
return tags | |||
|
|||
def _get_user(self, nick): | |||
def _get_user(self, user_id): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The WeechatChannelBuffer class was supposed to be protocol agnostic, that is it should not know what an user id is.
The idea was to make a higher level abstraction around a plain weechat buffer that implements actions like printing various message types, handling user joins, smart filtering, etc.
Other protocol scripts could reuse this then.
If we are going to introduce user ids into the WeechatChannelBuffer class then the separation between WeechatChannelBuffer and RoomBuffer doesn't make any sense anymore and they should be merged into a single class.
I prefer to leave the separation as it is but I'm also fine with a merged classes scenario, just not a combination of both.
Fyi, if you chose to leave the separation, the user_id -> nick mapping is handled in this hashmap https://github.com/poljar/weechat-matrix/blob/olm-command/matrix/buffer.py#L849
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have any other such abstract separations in you code somewhere?
If that's the only one with WeechatBuffer/RoomBuffer separation I would rather merge it if you don't mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is in config.py.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're going to merge the classes please separate this into separate commits to ease the reviewing.
msg = self._nick_change_message(user, old_nick, new_nick) | ||
|
||
# TODO add a option to disable smart filters | ||
tags.append(SCRIPT_NAME + "_smart_filter") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The irc plugin adds two more tags for nick changes: irc_nick1 and irc_nick2.
Those tags contain the old and new nick and as far as i remember the smart filtering algorithm needs them to unmask lines that belong to the old nick.
More info here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interesting, so i guess i cannot use spaces or special symbols in tags there during irc_nick1_%s construction. Will those tags serve any purpose for weechat if I strip displayname of whitespace, unicode and/or special symbols?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right, display names can contain spaces.
I guess we'll have to change the smart filter algorithm to just use the user_id, and put the user_id into the tags of every message.
matrix/buffer.py
Outdated
tags.append(SCRIPT_NAME + "_smart_filter") | ||
|
||
self.print_date_tags(msg, date, tags) | ||
self.add_smart_filtered_nick(user.nick) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to remove the old nick using remove_smart_filtered_nick(). The smart filter algorithm should then pick the old nick up from the tags just like it does in the irc plugin.
You don't need to make the smart filter algorithm work with nick changes for now. Just make sure to add the tags and remove the old nick here.
@@ -178,6 +178,12 @@ def upload(args): | |||
parser.add_argument("file") | |||
return WeechatCommandParser._run_parser(parser, args) | |||
|
|||
@staticmethod |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please put the /nick command addition into a separate commit.
@@ -640,22 +644,19 @@ def _get_prefix_color(prefix): | |||
|
|||
def _add_user_to_nicklist(self, user): | |||
# type: (WeechatUser) -> None | |||
nick_pointer = W.nicklist_search_nick(self._ptr, "", user.nick) | |||
|
|||
if not nick_pointer: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you remove the conditional here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, will bring it back
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is not required in new commit since nick_ptrs and duplicate nicks handled in separately
b05c6a0
to
c886174
Compare
I did not fix issue with WeechatChannelBuffer/RoomBuffer yet, but it would be nice if you can check if you're happy with my solution to nick disambiguation and smart filtering. It breaks nick autocompletion unfortunately but could be addressed with custom autocompletion for /input hook I guess (unless it also breaks something else). |
@@ -685,10 +718,29 @@ def _membership_message(self, user, message_type): | |||
|
|||
return message | |||
|
|||
def _nick_change_message(self, user, old_nick, new_nick): | |||
action_color = "purple" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Purple is not a valid weechat color, you can see the available colors with the /color
command after inputing e in the newly created buffer.
action_color = "purple" | ||
prefix = "network" | ||
|
||
message = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't print out the disambiguated nicks which can lead to confusion when we have duplicates, maybe it'll make sense to always print out the user id alongside the first nick?
Also if you want to color the message, please make it configurable. The irc nick change message uses the default color, I would stick to that as a default as well.
@@ -640,22 +652,43 @@ def _get_prefix_color(prefix): | |||
|
|||
def _add_user_to_nicklist(self, user): | |||
# type: (WeechatUser) -> None | |||
nick_pointer = W.nicklist_search_nick(self._ptr, "", user.nick) | |||
if user.nick in self.duplicate_nicks: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The disambiguation algorithm works well, great work. Sadly we forgot a crucial feature about it, the room display name depends on user display names if the room is unnamed.
Therefore the algorithm should go into nio, and weechat should ask nio when adding, removing, and changing nicks if there are conflicts. After a user is added, removed or a nick change is performed weechat needs to ask nio for the new room display name and set the buffers short_name property to that (it already does that to an extent).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you want nio to handle disambiguation in full or just put get_disambiguated_nick
into nio? I kinda have a feeling that nio is a bit more low-level to handle that...
Also I still feel it as a bit of controversy, I know that it is recommended by spec but I really want to avoid using fully disambiguated nicks in weechat room buffer (not in nicklist) since it makes output unwieldy or nick get cut by weechat.look.prefix_align_max
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you mean by full. Anything that is needed to calculate a disambiguated display name and the room name should go into nio. The client of course can pick and chose what it will display to the user. But the client should be able to ask nio for a disambiguated name.
So weechat remembers what it has displayed (it already does that), upon a join/leave or display name change it checks if it would have a conflict and if so asks nio for the disambiguated names.
The room name calculation is inside of nio, I don't see how room member name calculation is any higher or lower level than this. Especially since correct room name calculation depends on the room member names.
If you want to mix and match what gets displayed please make it configurable, I have a feeling that people will have different opinions on that. So 3 modes I guess, what we currently have (user ids without the host part), full display names, and your mixed mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry if it wasn't so clear, by full I mean that nio should track collisions and return disambiguated name only in case when there is a clash in a single the room. I understand that for room names this is kinda required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Frankly speaking if matrix-nio/matrix-nio#4 going to be merged current mode of using part of user_id without host for nicks would be inconsistent with automatic room names. Do you have a suggestion how to make automatic room names configurable in matrix-nio?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I'm missing something... Could you elaborate on why it would be inconsistent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case if you have a chat with account with display name "Foo" and user id @bar:example.org
and if matrix-nio/matrix-nio#4 would be merged named_room_name
is going to return room name as "Foo" but weechat nicklist going to contain "bar" instead of "Foo" which can be confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The room names are already inconsistent since they use the full user id and the nicklist the short/local part of the user id.
That being said a function that uses user ids instead of display names for room name calculation can be added to nio and the old behavior can be preserved that way. Another function that gives a room name consisting of only the local part of the user id is fine as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gordon-quad me? what?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, github falsly triggered on part of matrix user id @bar:example.org
tags_type = "message_private" if self.type == "private" else "message" | ||
tags = self._message_tags(user, tags_type) + (extra_tags or []) | ||
self._print_message(user, message, date, tags, extra_prefix) | ||
|
||
user.update_speaking_time(date) | ||
self.unmask_smart_filtered_nick(nick) | ||
if user.host: | ||
self.unmask_smart_filtered_nick(underscore_nonalnum(user.host)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to filter the user_id here, the spec disallows white-space, more info here. nio should take care of events that contain invalid user_ids.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i am more worried about other symbols, like '=' or '@'. Couldn't find in weechat docs if those are allowed so decided not to risk it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe they are fine since the IRC plugin tends to put host names into tags. Any UTF-8 string is fine but the tags get separated by a space, so that's why display names are problematic.
@@ -491,13 +495,13 @@ def _message_tags(self, user, message_type): | |||
|
|||
return tags | |||
|
|||
def _get_user(self, nick): | |||
def _get_user(self, user_id): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're going to merge the classes please separate this into separate commits to ease the reviewing.
@@ -347,6 +355,7 @@ def __init__(self, name, server_name, user): | |||
|
|||
self.name = "" | |||
self.users = {} # type: Dict[str, WeechatUser] | |||
self.duplicate_nicks = {} # type: Dict[str, List[WeechatUser]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use a defaultdict here, that way we can always use duplicate_nicks[nick].append().
Slowly trying to finish this PR. Issue is that keeping track of user display name in matrix-nio doesn't help with it in client since if I understand correctly events received during sync are processed in matrix-nio internally (and propagated to the state of matrix-nio room) and only then processed by the client. In this case if client will mindlessly pull display names from matrix-nio room and multiple events of change nick and/or messages received during one sync - this can generate inconsistent logs, for example if following event sequence will be received in one sync:
room.user_name("@alice:example.org") is going to return "Alice" despite that message was sent when Alice had display name "Alice1". In this case it seems to me that it is still inevitable to for client to keep track of display name changes, unless there is a possibility to process events one-by-one both in matrix-nio and client. I am not very familiar with the codebase so any advise here would be really helpful. |
There is no way to process events one-by-one. The way this problem could be solved is for nio to remember the room state transitions for the current sync, then let the user fetch the snapshot of the state with a event_id or a event object. So for example:
After a new sync is received the old transitions are cleared. Either that or some amount of duplication inside of Weechat would be fine as well. Keeping only the latest state in nio is still very useful because the majority of "joins" (m.room.member event with a join membership state) will happen when we login for the first time, that is the joins will be contained in the state part of the sync instead of the timeline. So the state transitions are only important for us if the event is part of the timeline. |
Ok, a little bit of an less crazy idea landed in nio here. Now we can go through events at the same pace nio does. But this will probably end up requiring a complete rewrite of the RoomBuffer class. If you're still interested in this please let me know, otherwise I'll go forward with this in the next month(s). |
Hi, what's the state of this pr? I'd be happy to help if necessary, I really want this feature. |
It's waiting for someone to pick it up and finish the Weechat side of things. Weechat currently goes through events after nio (the underlying matrix library) does. Weechat and its RoomBuffer class would need to be modified or even rewritten to utilize nio event callbacks. This way Weechat and nio go through events in sync and we can ask nio for the display name of a user if we need to do so. We would still cache currently used display names in Weechat inside the nicklist. We would ideally separate the event formatting code into a separate class so that it can be reused in different parts of Weechat. |
nick
command to change your display nameSpec recommends to use format "displayname (user id)" to remove ambiguity. In my case I used color for that because weechat nick column can be quite limited in width.
Depends on matrix-nio/matrix-nio#2