Skip to content

Admin

This example shows how to manage your group metadata and members.

Commands

Here are the commands to add and remove users:

cmd
/add @alix
/remove @bo
/name "New Group Name"

Main code

src/handler/admin.ts
import { HandlerContext } from "@xmtp/message-kit";
import type { User } from "@xmtp/message-kit";
 
// Reusable function to handle adding members
function handleAddMembers(
  addedInboxes: { inboxId: string }[],
  members: User[],
) {
  const addedNames = members
    ?.filter((member: User) =>
      addedInboxes.some(
        (added: { inboxId: string }) =>
          added?.inboxId?.toLowerCase() === member?.inboxId?.toLowerCase(),
      ),
    )
    .map((member: User) => `@${member.username}`)
    .filter((name: string) => name.trim() !== "@") // Filter out empty or undefined usernames
    .join(", "); // Join names for message formatting
 
  if (addedNames && addedNames.trim().length > 0) {
    let messages = [
      `Yo, ${addedNames}! ðŸŦĄ`,
      `LFG ${addedNames}!`,
      `${addedNames}ðŸĪ`,
    ];
    return messages[Math.floor(Math.random() * messages.length)];
  }
  return "";
}
function handleRemoveMembers() {
  let messages = [`ðŸŠĶ`, `ðŸ‘ŧ`, `hasta la vista, baby`];
  return messages[Math.floor(Math.random() * messages.length)];
}
const handleGroupname = (newValue: string, adminName: string) => {
  let messages = [`LFG '${newValue}'! ðŸ”Ĩ`, `all hail '${newValue}' 👏ðŸŧ`];
  return messages[Math.floor(Math.random() * messages.length)];
};
export async function handler(context: HandlerContext) {
  const {
    group,
    members,
    message: { content, typeId, sender },
  } = context;
 
  if (typeId === "group_updated") {
    const {
      initiatedByInboxId,
      metadataFieldChanges,
      removedInboxes,
      addedInboxes,
    } = content;
 
    // Fetch username from members array mapped by inboxId
    const adminName =
      members?.find((member) => member.inboxId === initiatedByInboxId)
        ?.username || "Admin";
 
    let message: string = "";
    if (addedInboxes && addedInboxes.length > 0) {
      message += handleAddMembers(addedInboxes, members!);
    } else if (removedInboxes && removedInboxes.length > 0) {
      message += handleRemoveMembers();
    } else if (metadataFieldChanges && metadataFieldChanges[0]) {
      const { fieldName, newValue } = metadataFieldChanges?.[0];
      if (fieldName === "group_name") {
        message += handleGroupname(newValue, adminName);
      }
    }
    await context.reply(message);
  } else if (typeId === "text") {
    const {
      params: { type, username, name },
    } = content;
    switch (type) {
      case "name":
        try {
          await group.updateName(name);
          const messages = handleGroupname(name, sender.username);
          context.reply(messages);
        } catch (error) {
          context.reply("No admin privileges");
          console.error(error);
        }
        break;
      case "remove":
        try {
          const removedInboxes = username.map((user: User) => user.inboxId);
          if (!removedInboxes || removedInboxes.length === 0) {
            context.reply("Wrong username");
            return;
          }
          await group.sync();
          await group.removeMembersByInboxId(removedInboxes);
          const messages = handleRemoveMembers();
          context.reply(messages);
        } catch (error) {
          context.reply("Error: Check admin privileges");
          console.error(error);
        }
        break;
      case "add":
        try {
          const addedInboxes = username.map((user: User) =>
            user?.inboxId?.toLowerCase(),
          );
          if (!addedInboxes || addedInboxes.length === 0) {
            context.reply("Wrong username");
            return;
          }
          await group.sync();
          await group.addMembersByInboxId(addedInboxes);
          await group.sync();
          const messages = handleAddMembers(
            [{ inboxId: addedInboxes[0] }],
            members!,
          );
          context.reply(messages);
        } catch (error) {
          context.reply("Error: Check admin privileges");
          console.error(error);
        }
        break;
    }
  }
  return;
}