{"action":"created","comment":{"url":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/comments/42100183","id":42100183,"diff_hunk":"@@ -10,20 +14,135 @@ Events\n \n {{m_room_message_feedback_event}}\n \n+Usage of this event is discouraged for several reasons:\n+ - The number of feedback events will grow very quickly with the number of users\n+   in the room. This event provides no way to \"batch\" feedback, unlike the\n+   `receipts module`_.\n+ - Pairing feedback to messages gets complicated when paginating as feedback\n+   arrives before the message it is acknowledging.\n+ - There are no guarantees that the client has seen the event ID being\n+   acknowledged.\n+\n+\n+.. _`receipts module`: `module:receipts`_\n+\n {{m_room_name_event}}\n \n {{m_room_topic_event}}\n \n m.room.message msgtypes\n------------------------\n-\n-.. TODO-spec\n-   How a client should handle unknown message types.\n-\n+~~~~~~~~~~~~~~~~~~~~~~~\n \n Each `m.room.message`_ MUST have a ``msgtype`` key which identifies the type\n of message being sent. Each type has their own required and optional keys, as\n-outlined below.\n+outlined below. If a client cannot display the given ``msgtype`` then it SHOULD\n+display the fallback plain text ``body`` key instead.\n \n {{msgtype_events}}\n \n+\n+Client behaviour\n+----------------\n+\n+Clients SHOULD verify the structure of incoming events to ensure that the\n+expected keys exist and that they are of the right type. Clients can discard\n+malformed events or display a placeholder message to the user. Redacted\n+``m.room.message`` events MUST be removed from the client. This can either be\n+replaced with placeholder text (e.g. \"[REDACTED]\") or the redacted message can\n+be removed entirely from the messages view.\n+\n+Events which have attachments (e.g. ``m.image``, ``m.file``) SHOULD be\n+uploaded using the `content repository module`_ where available. The\n+resulting ``mxc://`` URI can then be used in the ``url`` key.\n+\n+.. _`content repository module`: `module:content`_\n+\n+Recommendations when sending messages\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Clients can send messages using ``POST`` or ``PUT`` requests. Clients SHOULD use\n+``PUT`` requests with `transaction IDs`_ to make requests idempotent. This\n+ensures that messages are sent exactly once even under poor network conditions.\n+Clients SHOULD retry requests using an exponential-backoff algorithm for a\n+certain amount of time T. It is recommended that T is no longer than 5 minutes.\n+After this time, the client should stop retrying and mark the message as \"unsent\".\n+Users should be able to manually resend unsent messages.\n+\n+Users may type several messages at once and send them all in quick succession.\n+Clients SHOULD preserve the order in which they were sent by the user. This\n+means that clients should wait for the response to the previous request before\n+sending the next request. This can lead to head-of-line blocking. In order to\n+reduce the impact of head-of-line blocking, clients should use a queue per room\n+rather than a global queue, as ordering is only relevant within a single room\n+rather than between rooms.\n+\n+.. _`transaction IDs`: `sect:txn_ids`_\n+\n+Local echo\n+~~~~~~~~~~\n+\n+Messages SHOULD appear immediately in the message view when a user presses the\n+\"send\" button. This should occur even if the message is still sending. This is\n+referred to as \"local echo\". Clients SHOULD implement \"local echo\" of messages.\n+\n+Clients need to be able to match the message they are sending with the same\n+message which they receive from the event stream. The echo of the same message\n+from the event stream is referred to as \"remote echo\". Both echoes need to be\n+identified as the same message in order to prevent duplicate messages being\n+displayed. Ideally this pairing would occur transparently to the user: the UI\n+would not flicker as it transitions from local to remote. Flickering cannot be\n+fully avoided in version 1 of the client-server API. Two scenarios need to be\n+considered:\n+\n+- The client sends a message and the remote echo arrives on the event stream\n+  *after* the request to send the message completes.\n+- The client sends a message and the remote echo arrives on the event stream\n+  *before* the request to send the message completes.\n+\n+In the first scenario, the client will receive an event ID when the request to\n+send the message completes. This ID can be used to identify the duplicate event\n+when it arrives on the event stream. However, in the second scenario, the event\n+arrives before the client has obtained an event ID. This makes it impossible to\n+identify it as a duplicate event. This results in the client displaying the\n+message twice for a fraction of a second before the the original request to send\n+the message completes. Once it completes, the client can take remedial actions\n+to remove the duplicate event by looking for duplicate event IDs. Version 2 of\n+the client-server API resolves this by attaching the transaction ID of the\n+sending request to the event itself.\n+\n+\n+Displaying membership information with messages\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Clients may wish to show the display name and avatar URL of the room member who\n+sent a message. This can be achieved by inspecting the ``m.room.member`` state\n+event for that user ID.\n+\n+When a user paginates the message history, clients may wish to show the\n+**historical** display name and avatar URL for a room member. This is possible\n+because older ``m.room.member`` events are returned when paginating. This can\n+be implemented efficiently by keeping two sets of room state: old and current.\n+As new events arrive and/or the user paginates back in time, these two sets of\n+state diverge from each other. New events update the current state and paginated\n+events update the old state. When paginated events are processed sequentially,\n+the old state represents the state of the room *at the time the event was sent*.\n+This can then be used to set the historical display name and avatar URL.\n+\n+Server behaviour\n+----------------\n+\n+Homeservers SHOULD reject ``m.room.message`` events which don't have a\n+``msgtype`` key, or who don't have a textual ``body`` key, with an HTTP status","path":"specification/modules/instant_messaging.rst","position":null,"original_position":139,"commit_id":"f51ee706330be5904077b85b595d209794f290d3","original_commit_id":"4170dbd5cf065f7e1c7fde32f4c5a6e622c98055","user":{"login":"Kegsay","id":7190048,"avatar_url":"https://avatars.githubusercontent.com/u/7190048?v=3","gravatar_id":"","url":"https://api.github.com/users/Kegsay","html_url":"https://github.com/Kegsay","followers_url":"https://api.github.com/users/Kegsay/followers","following_url":"https://api.github.com/users/Kegsay/following{/other_user}","gists_url":"https://api.github.com/users/Kegsay/gists{/gist_id}","starred_url":"https://api.github.com/users/Kegsay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kegsay/subscriptions","organizations_url":"https://api.github.com/users/Kegsay/orgs","repos_url":"https://api.github.com/users/Kegsay/repos","events_url":"https://api.github.com/users/Kegsay/events{/privacy}","received_events_url":"https://api.github.com/users/Kegsay/received_events","type":"User","site_admin":false},"body":"Done","created_at":"2015-10-15T09:20:12Z","updated_at":"2015-10-15T09:20:12Z","html_url":"https://github.com/matrix-org/matrix-doc/pull/85#discussion_r42100183","pull_request_url":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/85","_links":{"self":{"href":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/comments/42100183"},"html":{"href":"https://github.com/matrix-org/matrix-doc/pull/85#discussion_r42100183"},"pull_request":{"href":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/85"}}},"pull_request":{"url":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/85","id":47012524,"html_url":"https://github.com/matrix-org/matrix-doc/pull/85","diff_url":"https://github.com/matrix-org/matrix-doc/pull/85.diff","patch_url":"https://github.com/matrix-org/matrix-doc/pull/85.patch","issue_url":"https://api.github.com/repos/matrix-org/matrix-doc/issues/85","number":85,"state":"open","locked":false,"title":"Instant messaging module","user":{"login":"Kegsay","id":7190048,"avatar_url":"https://avatars.githubusercontent.com/u/7190048?v=3","gravatar_id":"","url":"https://api.github.com/users/Kegsay","html_url":"https://github.com/Kegsay","followers_url":"https://api.github.com/users/Kegsay/followers","following_url":"https://api.github.com/users/Kegsay/following{/other_user}","gists_url":"https://api.github.com/users/Kegsay/gists{/gist_id}","starred_url":"https://api.github.com/users/Kegsay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kegsay/subscriptions","organizations_url":"https://api.github.com/users/Kegsay/orgs","repos_url":"https://api.github.com/users/Kegsay/repos","events_url":"https://api.github.com/users/Kegsay/events{/privacy}","received_events_url":"https://api.github.com/users/Kegsay/received_events","type":"User","site_admin":false},"body":"This PR changes the IM module to conform to the module template. It also adds in a lot of new information about client behaviour.","created_at":"2015-10-07T10:53:05Z","updated_at":"2015-10-15T09:20:12Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f9e4495164dffaab712e5785fe0802fa24208864","assignee":{"login":"Kegsay","id":7190048,"avatar_url":"https://avatars.githubusercontent.com/u/7190048?v=3","gravatar_id":"","url":"https://api.github.com/users/Kegsay","html_url":"https://github.com/Kegsay","followers_url":"https://api.github.com/users/Kegsay/followers","following_url":"https://api.github.com/users/Kegsay/following{/other_user}","gists_url":"https://api.github.com/users/Kegsay/gists{/gist_id}","starred_url":"https://api.github.com/users/Kegsay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kegsay/subscriptions","organizations_url":"https://api.github.com/users/Kegsay/orgs","repos_url":"https://api.github.com/users/Kegsay/repos","events_url":"https://api.github.com/users/Kegsay/events{/privacy}","received_events_url":"https://api.github.com/users/Kegsay/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/85/commits","review_comments_url":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/85/comments","review_comment_url":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/comments{/number}","comments_url":"https://api.github.com/repos/matrix-org/matrix-doc/issues/85/comments","statuses_url":"https://api.github.com/repos/matrix-org/matrix-doc/statuses/f51ee706330be5904077b85b595d209794f290d3","head":{"label":"matrix-org:module-im","ref":"module-im","sha":"f51ee706330be5904077b85b595d209794f290d3","user":{"login":"matrix-org","id":8418310,"avatar_url":"https://avatars.githubusercontent.com/u/8418310?v=3","gravatar_id":"","url":"https://api.github.com/users/matrix-org","html_url":"https://github.com/matrix-org","followers_url":"https://api.github.com/users/matrix-org/followers","following_url":"https://api.github.com/users/matrix-org/following{/other_user}","gists_url":"https://api.github.com/users/matrix-org/gists{/gist_id}","starred_url":"https://api.github.com/users/matrix-org/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matrix-org/subscriptions","organizations_url":"https://api.github.com/users/matrix-org/orgs","repos_url":"https://api.github.com/users/matrix-org/repos","events_url":"https://api.github.com/users/matrix-org/events{/privacy}","received_events_url":"https://api.github.com/users/matrix-org/received_events","type":"Organization","site_admin":false},"repo":{"id":24998719,"name":"matrix-doc","full_name":"matrix-org/matrix-doc","owner":{"login":"matrix-org","id":8418310,"avatar_url":"https://avatars.githubusercontent.com/u/8418310?v=3","gravatar_id":"","url":"https://api.github.com/users/matrix-org","html_url":"https://github.com/matrix-org","followers_url":"https://api.github.com/users/matrix-org/followers","following_url":"https://api.github.com/users/matrix-org/following{/other_user}","gists_url":"https://api.github.com/users/matrix-org/gists{/gist_id}","starred_url":"https://api.github.com/users/matrix-org/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matrix-org/subscriptions","organizations_url":"https://api.github.com/users/matrix-org/orgs","repos_url":"https://api.github.com/users/matrix-org/repos","events_url":"https://api.github.com/users/matrix-org/events{/privacy}","received_events_url":"https://api.github.com/users/matrix-org/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/matrix-org/matrix-doc","description":"Matrix Documentation (including The Spec)","fork":false,"url":"https://api.github.com/repos/matrix-org/matrix-doc","forks_url":"https://api.github.com/repos/matrix-org/matrix-doc/forks","keys_url":"https://api.github.com/repos/matrix-org/matrix-doc/keys{/key_id}","collaborators_url":"https://api.github.com/repos/matrix-org/matrix-doc/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/matrix-org/matrix-doc/teams","hooks_url":"https://api.github.com/repos/matrix-org/matrix-doc/hooks","issue_events_url":"https://api.github.com/repos/matrix-org/matrix-doc/issues/events{/number}","events_url":"https://api.github.com/repos/matrix-org/matrix-doc/events","assignees_url":"https://api.github.com/repos/matrix-org/matrix-doc/assignees{/user}","branches_url":"https://api.github.com/repos/matrix-org/matrix-doc/branches{/branch}","tags_url":"https://api.github.com/repos/matrix-org/matrix-doc/tags","blobs_url":"https://api.github.com/repos/matrix-org/matrix-doc/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/matrix-org/matrix-doc/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/matrix-org/matrix-doc/git/refs{/sha}","trees_url":"https://api.github.com/repos/matrix-org/matrix-doc/git/trees{/sha}","statuses_url":"https://api.github.com/repos/matrix-org/matrix-doc/statuses/{sha}","languages_url":"https://api.github.com/repos/matrix-org/matrix-doc/languages","stargazers_url":"https://api.github.com/repos/matrix-org/matrix-doc/stargazers","contributors_url":"https://api.github.com/repos/matrix-org/matrix-doc/contributors","subscribers_url":"https://api.github.com/repos/matrix-org/matrix-doc/subscribers","subscription_url":"https://api.github.com/repos/matrix-org/matrix-doc/subscription","commits_url":"https://api.github.com/repos/matrix-org/matrix-doc/commits{/sha}","git_commits_url":"https://api.github.com/repos/matrix-org/matrix-doc/git/commits{/sha}","comments_url":"https://api.github.com/repos/matrix-org/matrix-doc/comments{/number}","issue_comment_url":"https://api.github.com/repos/matrix-org/matrix-doc/issues/comments{/number}","contents_url":"https://api.github.com/repos/matrix-org/matrix-doc/contents/{+path}","compare_url":"https://api.github.com/repos/matrix-org/matrix-doc/compare/{base}...{head}","merges_url":"https://api.github.com/repos/matrix-org/matrix-doc/merges","archive_url":"https://api.github.com/repos/matrix-org/matrix-doc/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/matrix-org/matrix-doc/downloads","issues_url":"https://api.github.com/repos/matrix-org/matrix-doc/issues{/number}","pulls_url":"https://api.github.com/repos/matrix-org/matrix-doc/pulls{/number}","milestones_url":"https://api.github.com/repos/matrix-org/matrix-doc/milestones{/number}","notifications_url":"https://api.github.com/repos/matrix-org/matrix-doc/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/matrix-org/matrix-doc/labels{/name}","releases_url":"https://api.github.com/repos/matrix-org/matrix-doc/releases{/id}","created_at":"2014-10-09T16:41:02Z","updated_at":"2015-10-14T14:44:59Z","pushed_at":"2015-10-15T09:19:54Z","git_url":"git://github.com/matrix-org/matrix-doc.git","ssh_url":"git@github.com:matrix-org/matrix-doc.git","clone_url":"https://github.com/matrix-org/matrix-doc.git","svn_url":"https://github.com/matrix-org/matrix-doc","homepage":null,"size":4004,"stargazers_count":20,"watchers_count":20,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":15,"forks":5,"open_issues":15,"watchers":20,"default_branch":"master"}},"base":{"label":"matrix-org:master","ref":"master","sha":"a320d58948d6aa2d39eac3f95685276e4b25eef1","user":{"login":"matrix-org","id":8418310,"avatar_url":"https://avatars.githubusercontent.com/u/8418310?v=3","gravatar_id":"","url":"https://api.github.com/users/matrix-org","html_url":"https://github.com/matrix-org","followers_url":"https://api.github.com/users/matrix-org/followers","following_url":"https://api.github.com/users/matrix-org/following{/other_user}","gists_url":"https://api.github.com/users/matrix-org/gists{/gist_id}","starred_url":"https://api.github.com/users/matrix-org/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matrix-org/subscriptions","organizations_url":"https://api.github.com/users/matrix-org/orgs","repos_url":"https://api.github.com/users/matrix-org/repos","events_url":"https://api.github.com/users/matrix-org/events{/privacy}","received_events_url":"https://api.github.com/users/matrix-org/received_events","type":"Organization","site_admin":false},"repo":{"id":24998719,"name":"matrix-doc","full_name":"matrix-org/matrix-doc","owner":{"login":"matrix-org","id":8418310,"avatar_url":"https://avatars.githubusercontent.com/u/8418310?v=3","gravatar_id":"","url":"https://api.github.com/users/matrix-org","html_url":"https://github.com/matrix-org","followers_url":"https://api.github.com/users/matrix-org/followers","following_url":"https://api.github.com/users/matrix-org/following{/other_user}","gists_url":"https://api.github.com/users/matrix-org/gists{/gist_id}","starred_url":"https://api.github.com/users/matrix-org/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matrix-org/subscriptions","organizations_url":"https://api.github.com/users/matrix-org/orgs","repos_url":"https://api.github.com/users/matrix-org/repos","events_url":"https://api.github.com/users/matrix-org/events{/privacy}","received_events_url":"https://api.github.com/users/matrix-org/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/matrix-org/matrix-doc","description":"Matrix Documentation (including The Spec)","fork":false,"url":"https://api.github.com/repos/matrix-org/matrix-doc","forks_url":"https://api.github.com/repos/matrix-org/matrix-doc/forks","keys_url":"https://api.github.com/repos/matrix-org/matrix-doc/keys{/key_id}","collaborators_url":"https://api.github.com/repos/matrix-org/matrix-doc/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/matrix-org/matrix-doc/teams","hooks_url":"https://api.github.com/repos/matrix-org/matrix-doc/hooks","issue_events_url":"https://api.github.com/repos/matrix-org/matrix-doc/issues/events{/number}","events_url":"https://api.github.com/repos/matrix-org/matrix-doc/events","assignees_url":"https://api.github.com/repos/matrix-org/matrix-doc/assignees{/user}","branches_url":"https://api.github.com/repos/matrix-org/matrix-doc/branches{/branch}","tags_url":"https://api.github.com/repos/matrix-org/matrix-doc/tags","blobs_url":"https://api.github.com/repos/matrix-org/matrix-doc/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/matrix-org/matrix-doc/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/matrix-org/matrix-doc/git/refs{/sha}","trees_url":"https://api.github.com/repos/matrix-org/matrix-doc/git/trees{/sha}","statuses_url":"https://api.github.com/repos/matrix-org/matrix-doc/statuses/{sha}","languages_url":"https://api.github.com/repos/matrix-org/matrix-doc/languages","stargazers_url":"https://api.github.com/repos/matrix-org/matrix-doc/stargazers","contributors_url":"https://api.github.com/repos/matrix-org/matrix-doc/contributors","subscribers_url":"https://api.github.com/repos/matrix-org/matrix-doc/subscribers","subscription_url":"https://api.github.com/repos/matrix-org/matrix-doc/subscription","commits_url":"https://api.github.com/repos/matrix-org/matrix-doc/commits{/sha}","git_commits_url":"https://api.github.com/repos/matrix-org/matrix-doc/git/commits{/sha}","comments_url":"https://api.github.com/repos/matrix-org/matrix-doc/comments{/number}","issue_comment_url":"https://api.github.com/repos/matrix-org/matrix-doc/issues/comments{/number}","contents_url":"https://api.github.com/repos/matrix-org/matrix-doc/contents/{+path}","compare_url":"https://api.github.com/repos/matrix-org/matrix-doc/compare/{base}...{head}","merges_url":"https://api.github.com/repos/matrix-org/matrix-doc/merges","archive_url":"https://api.github.com/repos/matrix-org/matrix-doc/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/matrix-org/matrix-doc/downloads","issues_url":"https://api.github.com/repos/matrix-org/matrix-doc/issues{/number}","pulls_url":"https://api.github.com/repos/matrix-org/matrix-doc/pulls{/number}","milestones_url":"https://api.github.com/repos/matrix-org/matrix-doc/milestones{/number}","notifications_url":"https://api.github.com/repos/matrix-org/matrix-doc/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/matrix-org/matrix-doc/labels{/name}","releases_url":"https://api.github.com/repos/matrix-org/matrix-doc/releases{/id}","created_at":"2014-10-09T16:41:02Z","updated_at":"2015-10-14T14:44:59Z","pushed_at":"2015-10-15T09:19:54Z","git_url":"git://github.com/matrix-org/matrix-doc.git","ssh_url":"git@github.com:matrix-org/matrix-doc.git","clone_url":"https://github.com/matrix-org/matrix-doc.git","svn_url":"https://github.com/matrix-org/matrix-doc","homepage":null,"size":4004,"stargazers_count":20,"watchers_count":20,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":15,"forks":5,"open_issues":15,"watchers":20,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/85"},"html":{"href":"https://github.com/matrix-org/matrix-doc/pull/85"},"issue":{"href":"https://api.github.com/repos/matrix-org/matrix-doc/issues/85"},"comments":{"href":"https://api.github.com/repos/matrix-org/matrix-doc/issues/85/comments"},"review_comments":{"href":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/85/comments"},"review_comment":{"href":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/matrix-org/matrix-doc/pulls/85/commits"},"statuses":{"href":"https://api.github.com/repos/matrix-org/matrix-doc/statuses/f51ee706330be5904077b85b595d209794f290d3"}}}}