EasySlack 1.0.1
dotnet add package EasySlack --version 1.0.1
NuGet\Install-Package EasySlack -Version 1.0.1
<PackageReference Include="EasySlack" Version="1.0.1" />
<PackageVersion Include="EasySlack" Version="1.0.1" />
<PackageReference Include="EasySlack" />
paket add EasySlack --version 1.0.1
#r "nuget: EasySlack, 1.0.1"
#:package EasySlack@1.0.1
#addin nuget:?package=EasySlack&version=1.0.1
#tool nuget:?package=EasySlack&version=1.0.1
EasySlack
<img src="assets/icon-grey.png" width="128" height="128" alt="EasySlack icon" />
EasySlack is a native C# Slack connector built directly on Slack Web API and Socket Mode. It avoids a dependency on a third-party Slack wrapper while providing a small, focused API for validation, sending messages, threaded replies, and receiving inbound Slack message events.
Projects
src/EasySlack: class library containing the connector, auth/options models, Web API calls, and Socket Mode event handlingsrc/EasySlackConsole: interactive console app usingInputtyfor manual Slack testingsrc/Test.Automated: console-based automated test runner with pass/fail output per test, suite summary, total runtime, and failed test enumeration
Current Capabilities
- Instantiate a connector from Slack auth material
- Validate bot-token connectivity using
auth.test - Send a message to a channel or conversation using
chat.postMessage - Send a threaded reply to a channel or conversation using
thread_ts - Send a message to a user by opening a direct conversation with
conversations.open - Retrieve basic conversation metadata with
conversations.info - Retrieve basic user metadata with
users.info - Receive Socket Mode message events over WebSocket
- Surface inbound
thread_tsfor threaded message handling - Fire async events for:
- message received
- connected
- disconnected
- action required
Slack App Setup
Start at https://api.slack.com/apps/ and create a new Slack app From scratch.
For the current version of EasySlack, the runtime only needs:
- a bot token starting with
xoxb- - an app-level token starting with
xapp-
1. Basic Information
After the app is created, open Basic Information.
This page contains several values commonly grouped together as "Slack auth information":
- App ID
- Client ID
- Client Secret
- Signing Secret
- Verification Token
What they are for:
- App ID: Slack's identifier for the app, usually
A... - Client ID: used in OAuth authorization flows
- Client Secret: used when exchanging OAuth authorization codes for tokens
- Signing Secret: used to verify inbound HTTP requests from Slack
- Verification Token: legacy compatibility value; Slack recommends the Signing Secret instead
EasySlack does not currently use those values directly at runtime, but you may need them later if you add distributed OAuth installs, HTTP-delivered Events API, slash commands, or interactivity.
While still on Basic Information, find App-Level Tokens and click Generate Token and Scopes.
Create an app-level token with:
connections:write
Slack will issue a token starting with xapp-.
Use that value as:
SlackAuthMaterial.AppToken
2. Set The App Icon
Still under Basic Information, go to Display Information and upload the app icon.
Recommended:
- use a square PNG
- use an icon that remains readable at small sizes
3. Enable Socket Mode
Open Socket Mode under Settings and enable it.
If you do not see Socket Mode, the app is likely not the right app type for this workflow. In practice, the cleanest fix is usually to create a fresh modern Slack app and configure it again from scratch.
Socket Mode means:
- Slack does not send events to your public web server
- your app opens an authenticated WebSocket connection to Slack
- Slack delivers Events API payloads over that WebSocket
4. Add OAuth Scopes
Open OAuth & Permissions and add these Bot Token Scopes:
channels:historychannels:readchat:writegroups:historygroups:readim:historyim:readim:writempim:historympim:readmpim:writeusers:read
Optional but useful:
chat:write.publicapp_mentions:read
What these scopes are for:
- Message subscription and read access:
channels:historygroups:historyim:historympim:history
- Metadata lookup:
channels:readgroups:readim:readmpim:readusers:read
- Sending messages:
chat:write
- Sending a direct message to a user via
SendMessageToUserAsync:im:write
- Multi-person DM creation or opening:
mpim:write
- Posting to public channels without first inviting the app:
chat:write.public
- Receiving
@YourAppNamementions in channels:app_mentions:read
Important:
- After changing scopes, click Reinstall to Workspace or the new scopes will not take effect.
5. Enable Event Subscriptions
Open Event Subscriptions under Features and enable them.
Important distinction:
- Socket Mode removes the need for a public inbound HTTP endpoint
- but you still must enable Event Subscriptions
- and you still must add the bot events you want Slack to deliver
When Socket Mode is enabled correctly, Slack should display a message similar to:
Socket Mode is enabled. You won't need to specify a Request URL.
Under Subscribe to bot events, add the events you need:
message.channelsfor public-channel messagesmessage.groupsfor private-channel messagesmessage.imfor direct-message eventsmessage.mpimfor multi-person direct-message eventsapp_mentionif you want the app to receive@YourAppNamementions in channels
Important distinction:
message.channelsis an event subscription, not a scopemessage.groupsis an event subscription, not a scopemessage.imis an event subscription, not a scopemessage.mpimis an event subscription, not a scopeapp_mentionis an event subscription, not a scopeapp_mentions:readis a scope
6. Install Or Reinstall The App
In the left navigation under Settings, click Install App, then click Install to Workspace or Reinstall to Workspace.
After approval, Slack generates the bot token shown as:
- Bot User OAuth Token
That token:
- usually starts with
xoxb- - is the token
EasySlackuses for:auth.testchat.postMessageconversations.infoconversations.openusers.info
Use that value as:
SlackAuthMaterial.BotToken
7. Invite The App To Conversations
Installing the app gives it credentials, but it does not automatically make the app a member of every conversation.
This is the most common cause of errors such as:
not_in_channel
For public channels:
- invite the app with
/invite @YourAppName - or grant
chat:write.publicif you want the app to post to public channels without being invited first
For private channels:
- the app must be explicitly invited
chat:write.publicdoes not help- open the private channel and run:
/invite @YourAppName
For direct messages:
SendMessageToUserAsyncexpects a user ID such asU...- it does not expect a DM conversation ID such as
D... - the library opens or reuses the DM conversation automatically
- this requires
im:write
How To Find Slack IDs
EasySlack methods generally work with Slack IDs rather than human-readable names.
Common ID prefixes:
C...: public channelG...: private channelD...: direct-message conversationU...: userA...: app
How To Get A Channel ID
- Open the channel in Slack
- Look at the URL
- The last path segment is usually the channel or conversation ID
Example:
https://yourworkspace.slack.com/client/T12345678/C0123456789- Channel ID:
C0123456789
How To Get A User ID
- Open the user's profile in Slack
- Use Slack's copy-member-ID style action if your client exposes it
- If that option is not visible, inspect profile-related links or user-detail surfaces where the
U...identifier appears
Example:
- User ID:
U0123456789
Important ID Usage Rules
channel sendexpects a conversation ID such asC...,G..., orD...user sendexpects a user ID such asU...- once a DM exists, Slack represents it as a conversation ID such as
D... SendMessageToUserAsyncavoids needing theD...ID up front because it accepts aU...user ID and opens or reuses the DM conversation
Getting Started
Create Slack auth material with your bot token and app token, then build a connector from it.
using EasySlack;
using System.Threading;
SlackAuthMaterial auth = new SlackAuthMaterial(
"xoxb-your-bot-token",
"xapp-your-app-token");
SlackConnectorOptions options = new SlackConnectorOptions(auth)
{
AutoReconnect = true
};
using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
using SlackConnector connector = new SlackConnector(options, cancellationTokenSource);
Subscribe To A Channel
The connector raises MessageReceived for plain inbound Slack message events delivered through Socket Mode. Messages with a non-empty Slack subtype are skipped by default. Filter to the channel you care about inside the handler.
using EasySlack;
using System;
using System.Threading;
using System.Threading.Tasks;
SlackAuthMaterial auth = new SlackAuthMaterial(
"xoxb-your-bot-token",
"xapp-your-app-token");
SlackConnectorOptions options = new SlackConnectorOptions(auth);
using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
using SlackConnector connector = new SlackConnector(options, cancellationTokenSource);
string channelId = "C0123456789";
connector.MessageReceived += async (sender, eventArgs) =>
{
if (eventArgs.ChannelId == channelId)
{
string conversationKey = eventArgs.ThreadTimestamp ?? eventArgs.Timestamp ?? string.Empty;
Console.WriteLine("New message received.");
Console.WriteLine("User: " + eventArgs.UserId);
Console.WriteLine("Text: " + eventArgs.Text);
Console.WriteLine("Timestamp: " + eventArgs.Timestamp);
Console.WriteLine("Thread Timestamp: " + (eventArgs.ThreadTimestamp ?? "(top-level message)"));
Console.WriteLine("Conversation Key: " + conversationKey);
}
await Task.CompletedTask.ConfigureAwait(false);
};
await connector.StartAsync(cancellationTokenSource.Token).ConfigureAwait(false);
Console.WriteLine("Listening for messages. Press ENTER to stop.");
Console.ReadLine();
await connector.StopAsync(cancellationTokenSource.Token).ConfigureAwait(false);
Send A Message To A User
To send a direct message to a user, pass the Slack user ID to SendMessageToUserAsync. The connector opens or reuses the direct-message conversation before posting the message.
using EasySlack;
using System;
using System.Threading;
SlackAuthMaterial auth = new SlackAuthMaterial(
"xoxb-your-bot-token",
"xapp-your-app-token");
SlackConnectorOptions options = new SlackConnectorOptions(auth);
using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
using SlackConnector connector = new SlackConnector(options, cancellationTokenSource);
SlackSendMessageResult result = await connector
.SendMessageToUserAsync("U0123456789", "Hello from EasySlack.", cancellationTokenSource.Token)
.ConfigureAwait(false);
if (result.Ok)
{
Console.WriteLine("Message sent.");
Console.WriteLine("Conversation: " + result.ChannelId);
Console.WriteLine("Timestamp: " + result.Timestamp);
}
else
{
Console.WriteLine("Slack rejected the message: " + result.Error);
}
Send A Threaded Reply To A Conversation
To reply in an existing Slack thread, pass the channel or conversation ID plus the thread root timestamp to SendMessageToChannelAsync. Leave threadTimestamp empty to keep the existing top-level post behavior.
using EasySlack;
using System;
using System.Threading;
SlackAuthMaterial auth = new SlackAuthMaterial(
"xoxb-your-bot-token",
"xapp-your-app-token");
SlackConnectorOptions options = new SlackConnectorOptions(auth);
using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
using SlackConnector connector = new SlackConnector(options, cancellationTokenSource);
connector.MessageReceived += async (sender, eventArgs) =>
{
string replyThreadTimestamp = eventArgs.ThreadTimestamp ?? eventArgs.Timestamp ?? string.Empty;
if (eventArgs.ChannelId == "C0123456789" && !string.IsNullOrWhiteSpace(replyThreadTimestamp))
{
await connector
.SendMessageToChannelAsync(
eventArgs.ChannelId,
"Replying in the same thread.",
replyThreadTimestamp,
cancellationTokenSource.Token)
.ConfigureAwait(false);
}
};
For top-level Slack messages, ThreadTimestamp is usually null. Use eventArgs.ThreadTimestamp ?? eventArgs.Timestamp when you want a stable conversation key that works for both root posts and replies.
Build
cd C:\Code\EasySlack\src
dotnet build
dotnet run --project .\Test.Automated\Test.Automated.csproj --framework net8.0
dotnet run --project .\EasySlackConsole\EasySlackConsole.csproj --framework net8.0
Attribution
<a target="_blank" href="https://icons8.com/icon/OBMhWEebAWe9/slack-new">Slack New</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Initial release