Skip to content

Instantly share code, notes, and snippets.

@liamcottle
Created September 25, 2024 01:52
Show Gist options
  • Save liamcottle/9cca7d7f13dd528e3e241473d7f4c477 to your computer and use it in GitHub Desktop.
Save liamcottle/9cca7d7f13dd528e3e241473d7f4c477 to your computer and use it in GitHub Desktop.
MeshChat Group Chats

MeshChat Group Chats

A few thoughts on how I would build group chat functionality into MeshChat.

Do note, that this is not a true decentralised/distributed approach as the group chat server must be hosted by a single identity.

It would be nice for a truly distributed group chat, although when it comes to moderation, message retrieval and reliability, I think it would be too complex for an initial implementation.

Of course, everyone is welcome to build their own group chat system, these are just my ideas on what I'm thinking of implementing, nothing is set in stone :)

Ideas

  • All administrative actions such as moderation, kicking, banning and message history retrieval requests are sent to a single destination.
  • This single destination must be reachable to be able to perform any modifications to the group chat (other than messages via propagation node?).
  • Message history would be cached on the local MeshChat client, for reading when a user is offline.
  • New messages could be sent to a propagation node, for auto syncing to the group chat server when it becomes available again.
  • Ideally, messages sent to the group chat would be encrypted by the sender for each of the current members, which ensures they are only decryptable by the members of the group.
    • Unfortunately, this means we would need to encrypt and send/store 10k messages if we send 1 message to a group with 10k users
    • This also means new members will not be able to see message history, as the sender did not encrypt the message for the new recipient, and the group server would not have a key to decrypt it in order to encrypt it for the new recipient.
  • Regarding my mention of moderation, this goes against the idea of "cannot be subjected to outside control, manipulation or censorship." that Reticulum provides, however I still find it vital to have management in your own private group spaces.
    • I would prefer my personal group chats to not be spammed like crazy, and to have the ability to clean up any questionable content before it's seen on a wide scale.
    • If you want to have a group chat that's unmoderated, you could just spin up a new identity key, announce your group, let anyone join, and watch it go crazy!

RNS Destinations

Aspects

  • meshchat.group

    • used for interacting with the group server (run inside the MeshChat instance, or maybe standalone?)
    • fetching group info, members and message history etc
    • request to join groups
  • lxmf.delivery

    • standard lxmf destination where users can send messages to
    • group server will only accept messages from users that are a member of the group
    • allows any other lxmf client to send messages to the group, even if they don't support viewing the group messages themselves
    • this is an inbound destination, messages are received here, for the group, but users must fetch message history via the meshchat.group destination
    • custom data that we want to send with group chats could be stored in a custom LXMF field
  • ???

    • the group chat server should be able to send a packet/message to a member of a group chat to notify them of a new message
    • these notifications should be toggleable for the user, on the server, so the server doesn't need to send them if the user doesn't need them
      • in the case where they are rarely online, and only occasionally connect via a low bandwidth mode such as LoRa
      • user will only need to fetch latest x messages on demand
    • the client could either have an inbound destination hash that allows for these notifications, or just allow the server to send an lxmf message with custom fields
      • the issue with using lxmf custom fields, is that existing clients would try to show these messages as incoming DM's, when they are infact notifications

Request Handlers(?):

  • Could probably use the built in RNS request handlers
  • Either respond with JSON (easier to use, less efficient over the wire)
  • or, use protobuf (compact, can define named payload schema without sending names over the wire, fields are optional)
server_destination.register_request_handler("/api/v1/info",
    response_generator = group_info_response_generator,
    allow = RNS.Destination.ALLOW_ALL # other endpoints can use lookup for member status in database
)
  • /api/v1/info
    • fetch info about the group, such as public_display_name, member count, group chat server version etc
  • /api/v1/display-name/update
    • allow group members with permission to update group display name
  • /api/v1/messages
    • fetch message history from the group server
  • /api/v1/messages/delete
    • allow group members with permission to delete messages
  • /api/v1/members/kick
  • /api/v1/members/ban
    • kick or ban members from the group

Database Tables:

  • groups:

    • id
    • identity_hash
    • destination_hash
    • public_display_name
    • private_display_name
    • identity_private_key (for self hosted groups?)
  • group_members:

    • id
    • group_identity_hash
    • member_identity_hash
    • permissions: (allow member to perform administrative tasks via the group server etc)
    • created_at (when the member joined)
    • updated_at
  • group_banned_identities:

    • id
    • group_identity_hash
    • banned_identity_hash
    • reason (string)
    • created_at (when the identity was banned)
  • group_messages:

    • could probably use the existing messages table in MeshChat

Requirements

  • send messages via lxmf?
    • allows for sending via propagation nodes
    • supports the standard format for messages
    • custom message data would have to use custom fields
  • users should be able to create their own group chat
  • users should be able to moderate/delete messages in their own group
  • groups should be able to be public or private
  • any user can join a public group
  • users must be approved to join a private group
  • users should be able to leave a group, this should update the members list on the server
  • messages will be stored on the machine that is hosting/running the group chat destination address
  • messages can be downloaded from the group chat server directly
  • would be nice for users to be able to send a message to a propagation node, which can sync it to the group for them, but without delivery reports, this is no good
  • users should be able to discover groups, probably by having an announce directory
  • public groups will share a public name for discovery
  • private groups could have a public name, or opt to show "Private Group" instead, upon joining, the real group name is available

have a section that states

  • any message you send to this group can be seen, saved and shared to others outside of this group by existing members of this group
  • messages you send to the group are encrypted by the client for the group server destination, only the group server can decrypt your messages, which allows it to share with other group users
  • the group administrator (holder of identity keys) stores and controls all data in the group, it may at any time remove messages, or remove you from the group

think of a way to allow for non moderatable groups?

  • for the case where you don't want a single server/identity controling the entire group
  • users can join distributed groups
  • no one can delete messages from the group
  • users in the group could send a follow up command message saying they deleted a previous message, but clients don't have to honour this, standard clients would (like Element for Matrix)
  • messages are not stored on a server, they're distributed directly between users of the group
  • moderation/administration would become complex, because who has the power to make changes to group names etc?
  • allowing clients to fetch message history will also become complex
  • it's possible for the group to get split into disconnected network segments, which would need to converge at a later date
  • an alternative, is a "broadcast group". users can send messages out, to a group destination, (with routing support), but with no means for fetching message history
    • this is how meshtastic "public" chats work, you either receive the message, or you don't, and there's no history of missed messages
    • I don't like this idea, I want to be able to come back and see messages I missed out on, hence the need for storing and retrieving them from somewhere

Use Cases

Just a couple of ideas for how I would use a group chat, and how I'd expect them to function.

Create a public group chat

  • it gets announced with a public display name such as "MeshChat Public Chat"
  • anyone can join the group
  • anyone in the group can send messages to the group
  • group admin (owner of the keys for the destination hash) can moderate the group, kicking/banning users (adds their identity hash to block list), or deleting messages
  • group admin can set a stamp cost/proof of work required to be able to join a group, or send messages, this will help combat spam bots, where 10k users join and spam messages
  • each user that joins would need to perform the proof of work before being able to join (admin can set this requirement in announced app_data settings etc)
  • admin (owner of destination keys) can delegate permissions to other identity hashes, allowing those members to perform actions on the group server, such as kick/ban/manage settings

Create a private group chat

  • it gets announced with a public display name such as "Private Group"
  • ablitiy to set a private, internal display name such as "Cottle Family Chat", where this name is only available for retrieval if you are a member of the group
  • users request to join the group
  • admin can approve users to join the group (adds their identity hash to the allow list)
  • also has same functionalities as the public group chats
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment