From 0703f192460a739a45f8d4f123ca88e39af85e94 Mon Sep 17 00:00:00 2001 From: Jonathan de Jong Date: Sun, 21 Nov 2021 19:03:49 +0000 Subject: [PATCH 1/4] initial --- proposals/xxxx-mention-pushrule.md | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 proposals/xxxx-mention-pushrule.md diff --git a/proposals/xxxx-mention-pushrule.md b/proposals/xxxx-mention-pushrule.md new file mode 100644 index 00000000000..2df6e757c81 --- /dev/null +++ b/proposals/xxxx-mention-pushrule.md @@ -0,0 +1,51 @@ +# MSCXXXX: Mention Pushrule + +Pings in matrix can be inconsistent for someone coming from an environment where pings are explicit +(e.g. Discord, Telegram, Slack, Whatsapp, etc.) + +Currently, personal pings are governed by 2 push rules; match on display name, and match on username. + +However, due to a variety of reasons, these push rules can have false-positives, and a suitable +alternative that only gives notifications on explicit pings does not exist. + +## Proposal + +This proposal aims to change that, adding the following push rule; + +```json +{ + "rule_id": ".m.rule.pings_mxid", + "default": true, + "enabled": true, + "conditions": [ + { + "kind": "mxid_ping" + } + ], + "actions": [ + "notify", + { + "set_tweak": "sound", + "value": "default" + }, + { + "set_tweak": "highlight" + } + ] +} +``` + +And the following condition; `mxid_ping`. + +Currently, this condition should trigger if the user's MXID is found in `content.body`, +or `content.formatted_body`. + +Rationale: +> This is called MXID "ping", as "mention" and "contains" would not be good fits for +> future-proofing, one of the benefits of a separate condition is that, in the future, +> once more comprehensive mention techniques come to fruition (such as putting mentions +> in an array), the rule could still automatically apply with a small tweak. + +## Unstable prefix + +The unstable should be `.nl.automatia.rule.pings_mxid` From 7386a692af2de8d8269fe32670eeb2d7971fd233 Mon Sep 17 00:00:00 2001 From: Jonathan de Jong Date: Sun, 21 Nov 2021 19:06:19 +0000 Subject: [PATCH 2/4] rename --- .../{xxxx-mention-pushrule.md => 3517-mention-pushrule.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename proposals/{xxxx-mention-pushrule.md => 3517-mention-pushrule.md} (98%) diff --git a/proposals/xxxx-mention-pushrule.md b/proposals/3517-mention-pushrule.md similarity index 98% rename from proposals/xxxx-mention-pushrule.md rename to proposals/3517-mention-pushrule.md index 2df6e757c81..5cdc419249d 100644 --- a/proposals/xxxx-mention-pushrule.md +++ b/proposals/3517-mention-pushrule.md @@ -1,4 +1,4 @@ -# MSCXXXX: Mention Pushrule +# MSC3517: Mention Pushrule Pings in matrix can be inconsistent for someone coming from an environment where pings are explicit (e.g. Discord, Telegram, Slack, Whatsapp, etc.) From ab9104227f1629ebf14042a53f99702e278d55d9 Mon Sep 17 00:00:00 2001 From: Jonathan de Jong Date: Mon, 22 Nov 2021 13:51:28 +0100 Subject: [PATCH 3/4] Update proposals/3517-mention-pushrule.md Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --- proposals/3517-mention-pushrule.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/3517-mention-pushrule.md b/proposals/3517-mention-pushrule.md index 5cdc419249d..3e362020ca7 100644 --- a/proposals/3517-mention-pushrule.md +++ b/proposals/3517-mention-pushrule.md @@ -10,7 +10,7 @@ alternative that only gives notifications on explicit pings does not exist. ## Proposal -This proposal aims to change that, adding the following push rule; +This proposal aims to change that, adding the following default push rule: ```json { From adad5989fdb1ea1731dd7831d89044d9d5ebc0da Mon Sep 17 00:00:00 2001 From: Jonathan de Jong Date: Sat, 29 Jan 2022 18:57:34 +0000 Subject: [PATCH 4/4] Update according to review --- proposals/3517-mention-pushrule.md | 132 +++++++++++++++++++++++++++-- 1 file changed, 123 insertions(+), 9 deletions(-) diff --git a/proposals/3517-mention-pushrule.md b/proposals/3517-mention-pushrule.md index 3e362020ca7..245a376ab3e 100644 --- a/proposals/3517-mention-pushrule.md +++ b/proposals/3517-mention-pushrule.md @@ -35,17 +35,131 @@ This proposal aims to change that, adding the following default push rule: } ``` -And the following condition; `mxid_ping`. +And the following condition, `mxid_ping`, which is defined below. -Currently, this condition should trigger if the user's MXID is found in `content.body`, -or `content.formatted_body`. +### Triggering the rule -Rationale: -> This is called MXID "ping", as "mention" and "contains" would not be good fits for -> future-proofing, one of the benefits of a separate condition is that, in the future, -> once more comprehensive mention techniques come to fruition (such as putting mentions -> in an array), the rule could still automatically apply with a small tweak. +The process of determining if the `mxid_ping` condition should trigger is described with the following pseudocode; + +```py + +# event: the raw event, at least containing `type` and `content` +# mxid: the @-prefixed User ID (e.g. "@bob:example.com") +def should_trigger_mention(event: dict, mxid: str) -> bool: + # 1. If an event type is m.room.message; + if event.type == "m.room.message": + content = event.content + + # 1.1. In event content, test if `body` is present and contains mxid substring, trigger if so. + if "body" in content and content["body"].contains(mxid): + return True + + # 1.2. In event content, test if `format` is present, equals "org.matrix.custom.html", + # "formatted_body" is present, and is a string. If so; + if "format" in content and content["format"] == "org.matrix.custom.html" and \ + "formatted_body" in content and isinstance(content["formatted_body"], str): + + # 1.2.1. Check formatted_body with the html subroutine, + # if it returned true, trigger. + if check_html_mxid(content["formatted_body"], mxid): + return True + + # 2. For ExtEv checking, test if event type is m.room.message, or m.message. + # Also test if m.text or m.message exists in the event content. + # If so, run the extev subroutine, if it returned true, trigger. + if event.type in ["m.room.message", "m.message"] and \ + ("m.text" in event.content or "m.message" in event.content): + return should_trigger_mention_extev(event) + +# ExtEv subroutine +def should_trigger_mention_extev(extev_event: dict, mxid: str) -> bool: + content = extev_event.content + + # E.1. In event content, test if `m.text` is present and contains mxid substring, trigger if so. + if "m.text" in content and content["m.text"].contains(mxid): + return True + + # E.2. In event content, if `m.html` is present, run html subroutine on it, trigger if it returned true. + if "m.html" in content and check_html_mxid(content["m.html"], mxid): + return True + + # E.3. In event content, if `m.message` is present; + if "m.message" in content: + # E.3.1. Iterate over objects, for each... + for obj in content["m.message"]: + # E.3.2. ...if `mimetype` is "text/plain": + # test if `body` contains mxid substring, trigger if so. + if obj["mimetype"] == "text/plain" and obj["body"].contains(mxid): + return True + + # E.3.3. ...if `mimetype` is "text/html": + # run html subroutine on `body`, trigger if it returned true. + if obj["mimetype"] == "text/plain" and check_html_mxid(obj["body"], mxid): + return True + + # E.4. Fallback to False + return False + + +# Html subroutine +def check_html_mxid(html: str, mxid: str) -> bool: + from bs4 import BeautifulSoup + + # H.1. Interpret html string as HTML document. + html = BeautifulSoup(content["formatted_body"], 'html.parser') + + # H.2. Iterate over all tags. + for link in soup.find_all('a'): + + # H.2.1. Ensure and extract a `href` tag. + if "href" not in link: + continue + href = link["href"] + + # H.2.2. If href starts with "http" or "https"; + if href.startswith("http") or href.startswith("https"): + from urllib.parse import urlparse, unquote + + # H.2.2.1. Interpret href as a URL. + url = urlparse(href) + + # H.2.2.2. Ensure URL authority part is "matrix.to". + if url.netloc != "matrix.to": + continue + + # H.2.2.3. Grab URL fragment, unquote it, and test if it contains mxid substring, + # return true if so. + frag = url.fragment + if unquote(frag).contains(mxid): + return True + + # H.2.3. Convert a copy of the MXID to have its `@` character replaced with "matrix:u/" + matrix_uri_mxid = "matrix:u/" + mxid[1:] + + # H.2.4. Test if href starts with this converted Matrix URI MXID, if so, return true. + if href.startswith(matrix_uri_mxid): + return True + + # H.3 Fallback to returning false. + return False + +``` + +The above also takes into account a stablized version of +[MSC1767](https://github.com/matrix-org/matrix-doc/pull/1767), which, at the time of writing, +is poised to become stablized very soon. + +### Rationale + +The condition is called a MXID *ping* specifically, as it is abstract over any specific form +of detecting a mention, such as "contains", or "mention. + +It is the idea that, in the future, MSCs come around which add in more sophisticated methods of +embedding "pings" into messages (such as an explicit mention array), and that this condition can +be altered to automatically include those. ## Unstable prefix -The unstable should be `.nl.automatia.rule.pings_mxid` +The prefix for the rule should be `.nl.automatia.rule.pings_mxid` + +The prefix for the condition should be `nl.automatia.mxid_ping` \ No newline at end of file