ephemeraHQ / converse-app

https://converse.xyz
MIT License
38 stars 3 forks source link

Group Invite Links #42

Closed neekolas closed 3 weeks ago

neekolas commented 3 months ago

We are going to need group invite links for Converse. For ETHDenver, Converse put together a complicated concept where the invite links could be a developer surface. That solution required a bot to be an admin of every group, allowing the bot to read and write messages. That feels off-brand for us, especially since the app is going to be open source, and adds a bunch of complexity to the backend.

I’m proposing something more straightforward which will work on top of any group (even ones created through other apps) so long as the user has permissions to add and remove members.

To start, this is the most basic form of invite link. If you have the link you can join the group. But it offers a foundation for us to add things like token gating or other rules later. And it can become a developer surface later too, if we want.

High level flow

Existing group member creating a link

  1. User POSTs to the /inviteLink API with any metadata we want to show on the landing page
  2. The backend returns a new invite link with a unique URL.
  3. Save the invite_link to the client’s local DB (alongside the XMTP group_id) so that it can be shown in the UI for copy/paste later and used in push notification handlers

New group member

  1. Click the invite link
  2. Link takes you to a landing page on Converse.xyz which shows the group name, the inviter’s profile, and any other metadata we want to show.
  3. User clicks the Join button
    1. If the user does not have the Converse app they will go to the app store and be prompted to install it. Then they should go back to step 2*
    2. If the user does have the app, the app will open
  4. Upon landing in the app the client will send a request to the /groups/joinFromInvite API
  5. Backend triggers a push notification to the link creator
  6. The app opens to the conversation list view, with the new group grayed out to indicate a pending status
    1. Client can poll the API to see the state of the invite and know when the existing member has marked it as resolved

Existing member when someone clicks the link

  1. Receives push notification saying “User X joined Group Y through your invite link”
  2. In the background calls libxmtp to load the group and add the member
  3. Client calls API to mark the request as completed

*To handle cases where the push notification fails to deliver (maybe you’re offline for a long time or whatever) we can also have an API that lets clients check for any pending joins. Could run that on startup.

New APIs

POST /groupInvite

Used by the creator of an invite link to make a new link.

// Example request
{
    groupName: "XMTP Gang",
    groupImage: "https://....",
    // Inviter can be inferred from the request auth token.
    // Server doesn't need the actual group ID, since the client can keep track in their DB
}
// Example response
{
    id: "abcdefg",
    linkUrl: "https://converse.xyz/invite/abcdefg"
}

GET /groupInvite/:id

Used to generate the landing page for a group invite link

// Example response
{
    id: "abcdefg",
    linkUrl: "https://converse.xyz/invite/abcdefg",
    groupName: "XMTP Gang",
    groupImage: "https://....",
    createdBy: {
        // converse profile info
        ...
    }
}

POST /groupJoinRequest

Used by the recipient of an invite link to request to join the group.

// Example request
{
    inviteId: "abcdefg",
    // User info implied from auth token
}
// Example response
{
    id: "hijklmn" // The id of the join request
    status: 'pending'
}

GET /groupJoinRequest/:id

Used by the recipient of an invite link to check for the status of their request to join.

// Example response
{
    id: "hijlkmn",
    status: "approved" // Possible statuses ("approved", "rejected", "pending")
    reason: null // Allow the system to pass a reason back to the client
}

PUT /groupJoinRequest/:id

Used by the invite link creator to mark an invite as approved or rejected. For basic invite links, approval will happen immediately as soon as the push notification has been received.

// Example request
{
    status: "approved"
}
alexrisch commented 3 months ago

@neekolas this is awesome!

I have some questions about "Existing member when someone clicks the link"

  1. How are you defining an existing member? That they are in the group or on the network?
  2. The "In the background..." working as a silent notification to add the user and make the call to the network or something different?

I think "API that lets clients check for any pending joins" will be a necessity I think it's good for keep status of invites correct, and potentially helpful for multi admin groups

neekolas commented 3 months ago

@alexrisch the existing member is whoever created the invite link.

For a group with multiple admins, they will each see different links in the UI, since the invite link is tied to the creator and clicks get routed back to their phone.

I'm thinking this will be a visible notification (since you kinda want to know if someone joined the group). But could be silent too.

alexrisch commented 3 months ago

Makes sense, thank you for the clarification

neekolas commented 3 weeks ago

Great work @alexrisch. Can't wait to try it out.