Skip to content
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

Add: (ement-room-kick-user, ement-room-ban-user, ement-room-unban-user) New commands #297

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

phil-s
Copy link

@phil-s phil-s commented Sep 8, 2024

New admin commands for a room's power users.

@phil-s phil-s force-pushed the phil-s/ban-unban-user branch 2 times, most recently from a753291 to 430d9ef Compare September 8, 2024 03:49
@phil-s phil-s changed the title Add: (ement-room-ban-user, ement-room-unban-user) New commands Add: (ement-room-kick-user, ement-room-ban-user, ement-room-unban-user) New commands Sep 8, 2024
@phil-s phil-s marked this pull request as ready for review September 8, 2024 03:50
@phil-s phil-s force-pushed the phil-s/ban-unban-user branch 3 times, most recently from a78ad48 to 87e2652 Compare September 8, 2024 04:02
@phil-s
Copy link
Author

phil-s commented Sep 8, 2024

All done for now. Tested, and looking good, I think (for an initial version, at least).

@phil-s
Copy link
Author

phil-s commented Sep 8, 2024

Some comments of note from the testing:

It seemed to work pretty well from this side too: the ban message showed up in the room buffer, and the was moved into the [Left] group. When you unbanned me, the unban event showed up in the room buffer too.

Rejoining was a bit more work, because I had to get the room ID manually instead of using completion, but it worked once I was invited.

The other thing we might consider is to implement a convenience feature to also remove all recent events by the banned user, like Element offers to do when you ban someone. Helps with removing spam.

Can always delete the messages manually in the interim, though.

Interesting side effect: I killed the room buffer and reopened it so I could see and accept the invitation, then after rejoining, the events in the room that I already had are duplicated. I guess the server thinks we don't already have those events, so it sends them again, but we don't delete them, so we end up with multiple copies. Although I thought we already had code to deduplicate events…

Copy link
Owner

@alphapapa alphapapa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much for working on this!

@alphapapa alphapapa self-assigned this Sep 8, 2024
@alphapapa alphapapa added the enhancement New feature or request label Sep 8, 2024
@alphapapa alphapapa added this to the v0.16 milestone Sep 8, 2024
@phil-s
Copy link
Author

phil-s commented Sep 8, 2024

I see it's possible for the prompt to come up as "Ban user nil <@spammer123:matrix.org> ...?", so I should account for them not having a display name.

Copy link
Owner

@alphapapa alphapapa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for working on this.

@alphapapa
Copy link
Owner

alphapapa commented Sep 9, 2024

I see it's possible for the prompt to come up as "Ban user nil <@spammer123:matrix.org> ...?", so I should account for them not having a display name.

We should probably just add a convenience function to format users for display in these cases, e.g.

(cl-defun ement--format-user-id (user &key with-id-p (room ement-room))
  "Return string describing USER.
If ROOM, return the user's displayname in that room, when set;
otherwise, the user's global displayname.  If WITH-ID-P, quote
the displayname and include the user's MXID, like an email
address."
  (let ((displayname (if room
                         ;; FIXME: If a membership state event has not yet been received, this
                         ;; sets the display name in the room to the user ID, and that prevents
                         ;; the display name from being used if the state event arrives later.
                         (ement--user-displayname-in room user)
                       (or (ement-user-displayname user)
                           (ement-user-username user)))))
    (if with-id-p
        (if (equal displayname (ement-user-id user))
            ;; User has no displayname: just return the ID.
            (format "<%s>" displayname)
          (format "%S <%s>" displayname (ement-user-id user)))
      displayname)))

@alphapapa alphapapa modified the milestones: v0.16, v0.17 Sep 21, 2024
@phil-s
Copy link
Author

phil-s commented Sep 22, 2024

Cross-referencing with #300

@alphapapa
Copy link
Owner

By the way, I think we should add support for reporting messages to the homeserver admin. In Element, when I'm deleting spam, my procedure is usually: 1. Report to homeserver admin; 2. Ban user, 3. delete events.

@phil-s
Copy link
Author

phil-s commented Sep 23, 2024

I didn't know that was a thing.

https://spec.matrix.org/latest/client-server-api/#reporting-content

@phil-s phil-s force-pushed the phil-s/ban-unban-user branch from 684d865 to f803b99 Compare October 5, 2024 10:33
@phil-s
Copy link
Author

phil-s commented Oct 6, 2024

https://spec.matrix.org/latest/client-server-api/#reporting-content

Any thoughts on the "score" value when reporting?

A score ranges from -100 (worst/offensive) to zero (best/inoffensive), but I was finding this slightly awkward/ambiguous for UI purposes.

I decided to see what kind of UI Element presented for it, and... it doesn't. There's no score option at all. I used it to send a retrospective report for the last spam event, and the HTTP request contained a score of -100 in the JSON.

In the absence of any universally-agreed scale/mapping for the level of offence any given sort of post should warrant, "everything is -100" is certainly a simple solution.

We could provide a handful of pre-determined named values, but would need names like "Most offensive" down to "Inoffensive" rather than names like "Spam", as the latter would just be imposing our definitions of how offensive any given thing was.

We could have a very short labelled list like this, and default to... maybe -100, but maybe leaving space for something worse-than-normal?

-100 (most offensive)
-75 (very offensive)
-50 (quite offensive)
-25 (slightly offensive)
0 (inoffensive)

And even then, the labels on everything but the first and last items are quite subjective.

Thoughts?

@alphapapa
Copy link
Owner

alphapapa commented Oct 6, 2024

I appreciate your thoughtfulness, but I think we should just do what Element does here. If the official client doesn't care about offering a way to set the score parameter, then we probably shouldn't bother with it. (The score parameter was probably one of those things that seemed like a good idea at the time, but as you've aptly shown, doesn't map very well to reality and usability; the same content might be -100 HIGHLY OFFENSIVE to one person and -10 MEH to another and +1,000 WINS THE INTERNET to someone else.)

@phil-s
Copy link
Author

phil-s commented Oct 6, 2024

I've gone with "mimic Element by default" (sending -100 automatically without asking the user), but I've left the ability to select a score if a prefix argument is used. It's a little bit configurable in case anyone really wants to change the default but, on the basis that probably no one will do that, I left that pretty minimal.

@phil-s phil-s force-pushed the phil-s/ban-unban-user branch 2 times, most recently from f42be4b to c95c1b6 Compare October 12, 2024 10:36
@alphapapa alphapapa force-pushed the phil-s/ban-unban-user branch from 2ea60ad to 6cc93bf Compare October 12, 2024 22:39
@alphapapa
Copy link
Owner

@phil-s Thanks for your work and your patience. I pushed some "Minor changes" and rebased. Let me know if you agree that this is ready to merge.

@phil-s
Copy link
Author

phil-s commented Oct 13, 2024

Fair enough ditching the completing-read for score. I knew that seemed slightly mad by default, but I'd kept it so that users could change the list of options to a short list and then select from a handful of choices. I'm not fussed about losing that, though.

The refactor has lost the support for reporting without a score, though. Having -100 as a pre-populated input rather than "what you'll get by default" meant the user could submit an actual empty value, and we could then omit the score from the API request. With the new code you can't do that (and the documented nil behaviour for ement-room-report-content-score-default no longer applies, as read-number can't cope with that).

I think we need to revert to reading a string in order to support this.

@alphapapa
Copy link
Owner

Fair enough ditching the completing-read for score. I knew that seemed slightly mad by default, but I'd kept it so that users could change the list of options to a short list and then select from a handful of choices. I'm not fussed about losing that, though.

I feel like that's a case of "YAGNI." :)

The refactor has lost the support for reporting without a score, though. Having -100 as a pre-populated input rather than "what you'll get by default" meant the user could submit an actual empty value, and we could then omit the score from the API request. With the new code you can't do that (and the documented nil behaviour for ement-room-report-content-score-default no longer applies, as read-number can't cope with that).

I think we need to revert to reading a string in order to support this.

I checked the API, and it doesn't list the score as an optional field, so unless I'm missing something, I think we shouldn't submit it without one.

@phil-s
Copy link
Author

phil-s commented Oct 13, 2024

I'd figured everything not labelled Required was optional?

@alphapapa
Copy link
Owner

I'd figured everything not labelled Required was optional?

Well, I guess you're right. :) Would you mind testing to see what happens if we send a request without the reason and score fields, just to be certain? (I'd suggest sending it in the testing room we have, and then redacting the reported event; I think the matrix.org homeserver admins will forgive us for one unnecessary report since we're developing a client and the docs are a bit ambiguous about it.)

@phil-s
Copy link
Author

phil-s commented Oct 13, 2024

I reported a test message with no score, and I got a 200 response and the "Content reported." message.

I was tracing the plz call and confirmed it only had :body "{\"reason\":\"Testing. Please ignore.\"}" for the request body.

Edit: Whoops, you asked for no reason either. One moment...

@phil-s
Copy link
Author

phil-s commented Oct 13, 2024

Heh, ok, need to avoid this:

Error running timer `plz--respond': (ement-api-error "400: Content must be a JSON object.")

@phil-s
Copy link
Author

phil-s commented Oct 13, 2024

I believe this is good, now. I'm not seeing any errors from plz in any of the test scenarios. In each case I get the following from tracing plz:

(plz post "https://matrix-client.matrix.org/_matrix/client/r0/rooms/<roomid>/report/<eventid>?" :headers (("Authorization" . "Bearer <token>") ("Content-Type" . "application/json")) :body "<body>" :body-type text :as json-read :then #f(lambda (_data) [t] (message "Content reported.")) :else ement-api-error :connect-timeout 10 :timeout 60 :noquery t)

Where <body> is one of the following, depending on which optional arguments are supplied:

  • "{}"
  • "{\"reason\":\"Testing. Please ignore.\"}"
  • "{\"score\":0}"
  • "{\"score\":-10}"
  • "{\"score\":0,\"reason\":\"Testing. Please ignore.\"}"

@phil-s
Copy link
Author

phil-s commented Oct 13, 2024

Untested as yet, but I think we want this as well, so I'll just drop it in here for now.

(defun ement-room-report-delete-ban (event room session reason)
  "Report the current message, delete it, and ban the sender from the room."
  (interactive
   (ement-room-with-highlighted-event-at (point)
     (let ((event (ewoc-data (ewoc-locate ement-ewoc))))
       (unless (ement-event-p event)
         (user-error "No event at point"))
       (if (yes-or-no-p "Report, Delete, and Ban? ")
           (let ((reason (string-trim
                          (read-string "Reason: "
                                       nil ement-room-report-content-reason-history nil
                                       'inherit-input-method))))
             (list event ement-room ement-session reason))
         ;; Aborted.
         (let ((debug-on-quit nil))
           (signal 'quit nil))))))
  ;; Insist on a reason for this particular command.
  (when (string-empty-p reason)
    (user-error "Must supply a reason."))
  ;; Do all the things.
  (let ((user-id (ement-user-id (ement-event-sender event)))
        (room-id (ement-room-id room))
        (score ement-room-report-content-score-default))
    (ement-room-report-content event room session reason score)
    (ement-room-delete-message event room session reason)
    (ement-room-ban-user user-id room-id session reason)))

@alphapapa
Copy link
Owner

Thanks, we definitely need some kind of "do all the things" combo command. I think it'd be best to follow Element's lead here, i.e. when banning a user, maybe a prefix argument or two could be used to indicate that we want to also delete the user's recent content. So the workflow might be like: 1) report individual events that need reporting; 2) call the "ban user" command with a prefix argument, which would present a confirmation prompt like, "Ban user and delete user's recent events?". What do you think?

In the long run, it'd be nice to have a way to mark multiple events in a room buffer, and then call a command to act on them (e.g. if not all of a user's recent events should be reported). I have some ideas about how to facilitate that in the EWOC-based view. Let me know if you have any thoughts about that.

@phil-s
Copy link
Author

phil-s commented Oct 14, 2024

I hadn't thought about marking messages, but I had pondered iterating over all of that sender's messages and prompting the user to report/delete them all.

What about a search loop, highlighting each message from that sender in the room, and asking y-or-n-p for whether to add it to the list of messages to deal with? That might be relatively easy to implement.

I guess we could use (ement-room-occur :user-id sender) to bring up a buffer with just their messages, and make the selections from there?

@alphapapa
Copy link
Owner

Yeah, I like that idea. (Not expecting you to code it, necessarily, but feel free to if you are interested.)

@phil-s phil-s force-pushed the phil-s/ban-unban-user branch from a45b9a8 to 3852201 Compare November 17, 2024 04:42
@phil-s
Copy link
Author

phil-s commented Nov 17, 2024

Rebased over master, squashing some fixups.

@phil-s phil-s force-pushed the phil-s/ban-unban-user branch 2 times, most recently from e15249e to ceb0267 Compare February 13, 2025 10:14
@phil-s
Copy link
Author

phil-s commented Feb 13, 2025

I've pushed a command ement-room-report-delete-ban-selected for feedback.

You'll note that at present it doesn't issue the actual report/delete/ban requests (which have been pretty well-tested at this point, so ought to work). I've commented those lines out from this new function, and instead it just issues a message for each action, so that people can play with the UI and see if they like it.


Please note that all of the other commands in this PR do perform their actions, including the earlier ement-room-report-delete-ban (which acts only on the message at point).

Phil Sainty added 4 commits February 15, 2025 19:50
Interactively select the messages to report and delete.

FIXME: This is a test version, which only issues messages saying
what it would have done.
(ement-room-hide-message-content) New command
(ement-room-unhide-message-content) New command
@phil-s phil-s force-pushed the phil-s/ban-unban-user branch from f8717b8 to 617860d Compare February 15, 2025 06:52
@phil-s
Copy link
Author

phil-s commented Feb 21, 2025

I had an opportunity to use the new command in practice today (after I removed the training wheels, locally), and it worked fine.

I'm still interested in feedback on the UI (including whether it should even be a separate command in the menu, or just rolled into the "ban a user" command).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request priority:A
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants