mirror of
https://github.com/kc1awv/rrcd.git
synced 2026-06-08 14:11:53 -07:00
extend join and part messages
This commit is contained in:
@@ -2,6 +2,14 @@
|
||||
|
||||
This project follows the versioning policy in VERSIONING.md.
|
||||
|
||||
## 0.2.1 - 2026-01-08
|
||||
|
||||
- **JOINED/PARTED room notifications**: Existing room members now receive real-time notifications when users join or leave
|
||||
- When a user joins a room, existing members receive a `JOINED` message with the joining user's identity hash
|
||||
- When a user leaves a room, remaining members receive a `PARTED` message with the parting user's identity hash
|
||||
- Joining/parting users continue to receive the full member list (when `include_joined_member_list` is enabled)
|
||||
- See EX1-RRCD.md for detailed protocol documentation
|
||||
|
||||
## 0.2.0 - 2026-01-07
|
||||
|
||||
- **Major internal refactoring**: Improved code organization and maintainability
|
||||
|
||||
+82
@@ -271,6 +271,88 @@ periodically.
|
||||
room_invite_timeout_s = 900.0
|
||||
```
|
||||
|
||||
## Extension: JOINED and PARTED Room Notifications
|
||||
|
||||
The RRC specification defines `JOINED` and `PARTED` messages but doesn't specify
|
||||
whether room members should be notified when users join or leave. rrcd
|
||||
implements dual-mode notifications:
|
||||
|
||||
### JOIN Behavior
|
||||
|
||||
When a user joins a room:
|
||||
|
||||
1. **Joining user receives**: A `JOINED` message containing the full list of
|
||||
room members (if `include_joined_member_list` is enabled in config). This
|
||||
allows the client to know who is already in the room.
|
||||
|
||||
```python
|
||||
{
|
||||
0: 1, # protocol version
|
||||
1: T_JOINED, # message type
|
||||
2: <msg-id>,
|
||||
3: <timestamp>,
|
||||
4: <hub-identity-hash>, # src
|
||||
5: <room-name>,
|
||||
6: [<hash1>, <hash2>, ...] # body: list of all member identity hashes
|
||||
}
|
||||
```
|
||||
|
||||
2. **Existing room members receive**: A `JOINED` message containing **only** the
|
||||
identity hash of the user who just joined. This allows room members to update
|
||||
their member lists.
|
||||
|
||||
```python
|
||||
{
|
||||
0: 1,
|
||||
1: T_JOINED,
|
||||
2: <msg-id>,
|
||||
3: <timestamp>,
|
||||
4: <hub-identity-hash>,
|
||||
5: <room-name>,
|
||||
6: [<new-user-hash>] # body: single-element list
|
||||
}
|
||||
```
|
||||
|
||||
### PART Behavior
|
||||
|
||||
When a user leaves a room:
|
||||
|
||||
1. **Parting user receives**: A `PARTED` message containing the list of
|
||||
remaining room members (if `include_joined_member_list` is enabled).
|
||||
|
||||
2. **Remaining room members receive**: A `PARTED` message containing **only**
|
||||
the identity hash of the user who just left.
|
||||
|
||||
```python
|
||||
{
|
||||
0: 1,
|
||||
1: T_PARTED,
|
||||
2: <msg-id>,
|
||||
3: <timestamp>,
|
||||
4: <hub-identity-hash>,
|
||||
5: <room-name>,
|
||||
6: [<departed-user-hash>] # body: single-element list
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
```toml
|
||||
include_joined_member_list = true # default: true
|
||||
```
|
||||
|
||||
When disabled, all `JOINED` and `PARTED` messages have `null` or empty bodies.
|
||||
|
||||
### Client Implementation Notes
|
||||
|
||||
- **JOINED bodies** may contain either a full member list (multiple hashes) or a
|
||||
single hash. Clients should handle both cases.
|
||||
- **PARTED bodies** follow the same pattern.
|
||||
- The message source (`K_SRC`) is always the hub's identity hash, not the
|
||||
joining/parting user.
|
||||
- This extension allows clients to maintain accurate room member lists without
|
||||
polling or issuing `/who` commands after every join/part.
|
||||
|
||||
## Extension: Nickname Normalization
|
||||
|
||||
The RRC spec says nicknames are "advisory" and may be "ridiculous." rrcd
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
__all__ = ["__version__"]
|
||||
|
||||
__version__ = "0.2.0"
|
||||
__version__ = "0.2.1"
|
||||
|
||||
@@ -492,6 +492,24 @@ class MessageRouter:
|
||||
|
||||
self.hub.room_manager.touch_room(r)
|
||||
|
||||
# Notify existing room members about the new joiner
|
||||
# Send JOINED message with single identity hash to existing members
|
||||
existing_members = [
|
||||
member_link
|
||||
for member_link in self.hub.room_manager.get_room_members(r)
|
||||
if member_link != link
|
||||
]
|
||||
if existing_members:
|
||||
member_notification = make_envelope(
|
||||
T_JOINED, src=self.hub.identity.hash, room=r, body=[peer_hash]
|
||||
)
|
||||
member_notification_payload = encode(member_notification)
|
||||
for member_link in existing_members:
|
||||
self.hub.message_helper.queue_payload(
|
||||
outgoing, member_link, member_notification_payload
|
||||
)
|
||||
|
||||
# Send JOINED message with full member list to the joining user
|
||||
joined_body = None
|
||||
if self.hub.config.include_joined_member_list:
|
||||
members: list[bytes] = []
|
||||
@@ -563,6 +581,14 @@ class MessageRouter:
|
||||
return
|
||||
|
||||
sess["rooms"].discard(r)
|
||||
|
||||
# Get remaining members before removing the parting user
|
||||
remaining_members = [
|
||||
member_link
|
||||
for member_link in self.hub.room_manager.get_room_members(r)
|
||||
if member_link != link
|
||||
]
|
||||
|
||||
if self.hub.room_manager.get_room_members(r):
|
||||
self.hub.room_manager.remove_member(r, link)
|
||||
if not self.hub.room_manager.get_room_members(r):
|
||||
@@ -575,6 +601,19 @@ class MessageRouter:
|
||||
if st is not None and not st.get("registered"):
|
||||
self.hub.room_manager._room_state.pop(r, None)
|
||||
|
||||
# Notify remaining members about the user parting
|
||||
# Send PARTED message with single identity hash to remaining members
|
||||
if remaining_members:
|
||||
member_notification = make_envelope(
|
||||
T_PARTED, src=self.hub.identity.hash, room=r, body=[peer_hash]
|
||||
)
|
||||
member_notification_payload = encode(member_notification)
|
||||
for member_link in remaining_members:
|
||||
self.hub.message_helper.queue_payload(
|
||||
outgoing, member_link, member_notification_payload
|
||||
)
|
||||
|
||||
# Send PARTED message with current member list to the parting user
|
||||
parted_body = None
|
||||
if self.hub.config.include_joined_member_list:
|
||||
members: list[bytes] = []
|
||||
|
||||
Reference in New Issue
Block a user