Working with Groups
Signal.Bot provides comprehensive support for managing Signal groups.
Creating Groups
Create a new Signal group with members:
csharp
var client = new SignalBotClient("http://localhost:8080");
var botNumber = "+1234567890";
var group = await client.CreateGroupAsync(
number: botNumber,
name: "My Bot Group",
members: new[]
{
"+1111111111",
"+2222222222",
"+3333333333"
}
);
Console.WriteLine($"Created group: {group.Name}");
Console.WriteLine($"Group ID: {group.Id}");With Description and Avatar
csharp
var group = await client.CreateGroupAsync(
number: botNumber,
name: "Project Team",
members: new[] { "+1111111111", "+2222222222" },
description: "Our awesome project team",
avatar: "/path/to/group-avatar.jpg"
);Listing Groups
Get all groups the bot is a member of:
csharp
var groups = await client.ListGroupsAsync(botNumber);
foreach (var group in groups)
{
Console.WriteLine($"Group: {group.Name}");
Console.WriteLine($" ID: {group.Id}");
Console.WriteLine($" Members: {group.Members?.Count ?? 0}");
Console.WriteLine($" Is Blocked: {group.IsBlocked}");
Console.WriteLine();
}Getting Group Details
Retrieve detailed information about a specific group:
csharp
var groupId = "your-group-id-here";
var groupInfo = await client.GetGroupAsync(botNumber, groupId);
Console.WriteLine($"Name: {groupInfo.Name}");
Console.WriteLine($"Description: {groupInfo.Description}");
Console.WriteLine($"Members:");
foreach (var member in groupInfo.Members)
{
Console.WriteLine($" - {member.Number}");
}Updating Groups
Update Group Name
csharp
await client.UpdateGroupAsync(
number: botNumber,
groupId: groupId,
name: "Updated Group Name"
);Update Description
csharp
await client.UpdateGroupAsync(
number: botNumber,
groupId: groupId,
description: "New group description"
);Update Avatar
csharp
await client.UpdateGroupAsync(
number: botNumber,
groupId: groupId,
avatar: "/path/to/new-avatar.jpg"
);Add Members
csharp
await client.UpdateGroupAsync(
number: botNumber,
groupId: groupId,
addMembers: new[]
{
"+4444444444",
"+5555555555"
}
);Remove Members
csharp
await client.UpdateGroupAsync(
number: botNumber,
groupId: groupId,
removeMembers: new[] { "+4444444444" }
);Make Admins
csharp
await client.UpdateGroupAsync(
number: botNumber,
groupId: groupId,
admins: new[] { "+1111111111" }
);Update Everything at Once
csharp
await client.UpdateGroupAsync(
number: botNumber,
groupId: groupId,
name: "Updated Name",
description: "Updated description",
addMembers: new[] { "+6666666666" },
removeMembers: new[] { "+4444444444" },
admins: new[] { "+1111111111", "+2222222222" }
);Leaving Groups
Leave a group:
csharp
await client.QuitGroupAsync(botNumber, groupId);
Console.WriteLine($"Left group {groupId}");Deleting Groups
Delete a group (admin only):
csharp
await client.DeleteGroupAsync(botNumber, groupId);
Console.WriteLine($"Deleted group {groupId}");Sending Messages to Groups
Send a message to a group:
csharp
await client.SendMessageAsync(
number: botNumber,
message: "Hello everyone!",
groupId: groupId
);With Mentions
Mention specific members in the group:
csharp
await client.SendMessageAsync(
number: botNumber,
message: "Hey @John, check this out!",
groupId: groupId,
mentions: new[]
{
new Mention
{
Number = "+1111111111",
Start = 4, // Position of @John in the message
Length = 5 // Length of "John"
}
}
);Handling Group Messages
Receive and process group messages:
csharp
await client.StartReceiving(
botNumber,
handleMessage: async (botClient, message, ct) =>
{
// Check if it's a group message
if (!string.IsNullOrEmpty(message.DataMessage?.GroupId))
{
var groupId = message.DataMessage.GroupId;
var sender = message.Source;
var text = message.DataMessage.Message;
Console.WriteLine($"[Group: {groupId}] {sender}: {text}");
// Respond to group commands
if (text?.StartsWith("/group") == true)
{
await botClient.SendMessageAsync(
number: botNumber,
message: "Group command received!",
groupId: groupId,
cancellationToken: ct
);
}
}
},
handleError: async (botClient, exception, ct) =>
{
Console.WriteLine($"Error: {exception.Message}");
},
cancellationToken: CancellationToken.None
);Group Management Bot Example
A complete example of a group management bot:
csharp
public class GroupManagerBot
{
private readonly SignalBotClient _client;
private readonly string _botNumber;
private readonly HashSet<string> _adminNumbers;
public GroupManagerBot(SignalBotClient client, string botNumber, IEnumerable<string> admins)
{
_client = client;
_botNumber = botNumber;
_adminNumbers = new HashSet<string>(admins);
}
public async Task Start(CancellationToken cancellationToken)
{
await _client.StartReceiving(
_botNumber,
handleMessage: HandleGroupMessage,
handleError: HandleError,
cancellationToken: cancellationToken
);
}
private async Task HandleGroupMessage(SignalBotClient client, SignalMessage message, CancellationToken ct)
{
var groupId = message.DataMessage?.GroupId;
if (string.IsNullOrEmpty(groupId)) return;
var text = message.DataMessage?.Message;
if (string.IsNullOrEmpty(text)) return;
var sender = message.Source;
var isAdmin = _adminNumbers.Contains(sender);
switch (text.ToLower())
{
case "/groupinfo":
await ShowGroupInfo(groupId, ct);
break;
case "/members":
await ListMembers(groupId, ct);
break;
case var cmd when cmd.StartsWith("/kick ") && isAdmin:
var number = cmd.Replace("/kick ", "").Trim();
await KickMember(groupId, number, ct);
break;
case var cmd when cmd.StartsWith("/add ") && isAdmin:
var newMember = cmd.Replace("/add ", "").Trim();
await AddMember(groupId, newMember, ct);
break;
case "/help":
await ShowHelp(groupId, isAdmin, ct);
break;
}
}
private async Task ShowGroupInfo(string groupId, CancellationToken ct)
{
var group = await _client.GetGroupAsync(_botNumber, groupId);
var info = $@"📋 Group Information
Name: {group.Name}
Description: {group.Description ?? "N/A"}
Members: {group.Members?.Count ?? 0}
Admins: {group.Admins?.Count ?? 0}";
await _client.SendMessageAsync(
number: _botNumber,
message: info,
groupId: groupId,
cancellationToken: ct
);
}
private async Task ListMembers(string groupId, CancellationToken ct)
{
var group = await _client.GetGroupAsync(_botNumber, groupId);
var memberList = "👥 Group Members:\n" +
string.Join("\n", group.Members?.Select(m => $"- {m.Number}") ?? Array.Empty<string>());
await _client.SendMessageAsync(
number: _botNumber,
message: memberList,
groupId: groupId,
cancellationToken: ct
);
}
private async Task KickMember(string groupId, string number, CancellationToken ct)
{
try
{
await _client.UpdateGroupAsync(
number: _botNumber,
groupId: groupId,
removeMembers: new[] { number }
);
await _client.SendMessageAsync(
number: _botNumber,
message: $"✅ Removed {number} from the group",
groupId: groupId,
cancellationToken: ct
);
}
catch (Exception ex)
{
await _client.SendMessageAsync(
number: _botNumber,
message: $"❌ Failed to remove member: {ex.Message}",
groupId: groupId,
cancellationToken: ct
);
}
}
private async Task AddMember(string groupId, string number, CancellationToken ct)
{
try
{
await _client.UpdateGroupAsync(
number: _botNumber,
groupId: groupId,
addMembers: new[] { number }
);
await _client.SendMessageAsync(
number: _botNumber,
message: $"✅ Added {number} to the group",
groupId: groupId,
cancellationToken: ct
);
}
catch (Exception ex)
{
await _client.SendMessageAsync(
number: _botNumber,
message: $"❌ Failed to add member: {ex.Message}",
groupId: groupId,
cancellationToken: ct
);
}
}
private async Task ShowHelp(string groupId, bool isAdmin, CancellationToken ct)
{
var help = @"🤖 Group Bot Commands
Available to everyone:
/help - Show this message
/groupinfo - Show group information
/members - List all members";
if (isAdmin)
{
help += @"
Admin commands:
/kick <number> - Remove a member
/add <number> - Add a member";
}
await _client.SendMessageAsync(
number: _botNumber,
message: help,
groupId: groupId,
cancellationToken: ct
);
}
private async Task HandleError(SignalBotClient client, Exception exception, CancellationToken ct)
{
Console.WriteLine($"Error: {exception.Message}");
}
}
// Usage
var bot = new GroupManagerBot(
client,
"+1234567890",
new[] { "+9999999999" } // Admin numbers
);
await bot.Start(cts.Token);Best Practices
1. Store Group IDs Persistently
csharp
// Save group IDs to a database or file
public class GroupStore
{
private readonly Dictionary<string, string> _groups = new();
public void SaveGroup(string name, string id)
{
_groups[name] = id;
File.WriteAllText("groups.json", JsonSerializer.Serialize(_groups));
}
public string GetGroupId(string name)
{
return _groups.TryGetValue(name, out var id) ? id : null;
}
}2. Validate Permissions
csharp
private bool IsGroupAdmin(string groupId, string number)
{
var group = await _client.GetGroupAsync(_botNumber, groupId);
return group.Admins?.Any(a => a.Number == number) ?? false;
}3. Handle Group Events
csharp
await client.StartReceiving(
botNumber,
handleMessage: async (botClient, message, ct) =>
{
// Member joined
if (message.DataMessage?.GroupInfo?.Type == "MEMBER_ADDED")
{
await botClient.SendMessageAsync(
number: botNumber,
message: "Welcome to the group! 👋",
groupId: message.DataMessage.GroupId,
cancellationToken: ct
);
}
// Member left
if (message.DataMessage?.GroupInfo?.Type == "MEMBER_LEFT")
{
// Handle member leaving
}
},
handleError: HandleError,
cancellationToken: cts.Token
);Next Steps
- Learn about attachments
- Explore profile management
- Check out advanced examples
