slack-live
v0.3.0
Published
Real-time updating Slack messages with progress tracking
Downloads
510
Maintainers
Readme
slack-live
Real-time updating Slack messages with progress tracking.
Features
- Real-time message updates - Create and update Slack messages programmatically
- Progress bars - 6 customizable ASCII progress bar styles
- State management - Track message states (pending, running, completed, failed, cancelled)
- Presets - Ready-to-use templates for status, progress, pipelines, and encoding jobs
- Block Kit support - Fluent builder for rich Slack layouts
- Rate limiting - Automatic retry with exponential backoff
- TypeScript - Full type safety with strict mode
Installation
npm install slack-live
# or
pnpm add slack-live
# or
yarn add slack-liveQuick Start
import { SlackLive } from 'slack-live';
const slackLive = new SlackLive({
token: process.env.SLACK_BOT_TOKEN!,
defaultChannel: '#builds',
});
// Create a live message
const message = await slackLive.create('#builds', { text: 'Starting deployment...' });
// Update with progress
await message.setProgress(25);
await message.setText('Building Docker image...');
await message.setProgress(50);
await message.setText('Pushing to registry...');
await message.setProgress(75);
await message.setText('Deploying to production...');
// Complete the message
await message.complete('Deployment successful!');API Reference
SlackLive Client
const client = new SlackLive({
token: string; // Slack Bot Token (required)
defaultChannel?: string; // Default channel for messages
defaultProgressStyle?: ProgressBarStyle; // Default progress bar style
retryOptions?: {
maxRetries?: number; // Max retry attempts (default: 3)
initialDelay?: number; // Initial delay in ms (default: 1000)
maxDelay?: number; // Max delay in ms (default: 30000)
backoffMultiplier?: number; // Backoff multiplier (default: 2)
};
});Methods
create(channel, options, callbacks?)- Create a new live messagetask(label, options?)- Create a task for workflow trackingsync(channel, state)- Sync multiple tasks declarativelygetMessage(ts)- Get a message by timestampgetActiveMessages()- Get all non-finished messagesgetAllMessages()- Get all tracked messages
LiveMessage
const message = await client.create('#builds', { text: 'Hello' });
// Update content
await message.setText('New text');
await message.setBlocks(blocks);
await message.update({ text: 'Updated', blocks: [...] });
// Progress tracking
await message.setProgress(50); // Shows: [████████░░░░░░░░] 50%
// State transitions
await message.complete('Done!'); // completed state
await message.fail('Error'); // failed state
await message.cancel('Stopped'); // cancelled stateTask API
Higher-level abstraction for workflow steps:
const task = client.task('Processing files', { channel: '#builds' });
await task.start();
await task.update({ progress: 25, status: 'Reading files...' });
await task.log('Processed file1.txt');
await task.log('Processed file2.txt');
await task.update({ progress: 75, status: 'Writing output...' });
await task.succeed('All files processed!');Sync API
Declarative task synchronization:
// Separate messages (one per task)
await client.sync('#builds', {
layout: 'separate',
tasks: [
{ id: 'build', label: 'Build', status: 'completed', progress: 100 },
{ id: 'test', label: 'Test', status: 'running', progress: 60 },
{ id: 'deploy', label: 'Deploy', status: 'pending' },
],
});
// Combined message (all tasks in one)
await client.sync('#builds', {
layout: 'combined',
tasks: [...],
});Presets
Ready-to-use message templates:
Status Preset
await client.presets.status('#builds', {
title: 'Deployment',
status: 'running',
subtitle: 'Building Docker image...',
});
// Renders:
// 🔄 *Deployment*
// Building Docker image...Progress Preset
await client.presets.progress('#builds', {
title: 'Video Encoding',
progress: 45,
details: [
{ label: 'Format', value: 'H.264' },
{ label: 'ETA', value: '2m 30s' },
],
});
// Renders:
// 🔄 *Video Encoding*
// [███████░░░░░░░░░] 45%
//
// *Format:* H.264
// *ETA:* 2m 30sPipeline Preset
await client.presets.pipeline('#builds', {
title: 'CI/CD Pipeline',
steps: [
{ name: 'Build', status: 'completed' },
{ name: 'Test', status: 'running', progress: 60 },
{ name: 'Deploy', status: 'pending' },
],
});
// Renders:
// *CI/CD Pipeline*
// ────────────────────
// ✅ Build
// 🔄 Test [██████░░░░] 60%
// ⏳ DeployEncoding Job Preset
await client.presets.encodingJob('#builds', {
title: 'video.mp4',
jobId: '12345',
source: { duration: '1:30', resolution: '4K', size: '500MB' },
formats: [
{ name: '1080p', status: 'completed', size: '100MB', duration: '30s' },
{ name: '720p', status: 'running', progress: 65 },
{ name: '480p', status: 'pending' },
],
links: { manifest: 'https://example.com/manifest.json' },
});Updating Presets
Each preset returns a specialized message class that preserves the config state and provides typed update methods:
// Create an encoding job
const job = await client.presets.encodingJob('#builds', {
title: 'video.mp4',
formats: [
{ name: '1080p', status: 'pending' },
{ name: '720p', status: 'pending' },
],
});
// Update a specific format by name
await job.updateFormatByName('1080p', { status: 'running', progress: 25 });
// Update progress
await job.updateFormatByName('1080p', { progress: 75 });
// Complete the format
await job.updateFormatByName('1080p', {
status: 'completed',
size: '100MB',
duration: '30s',
});
// Complete job with links
await job.completeWithLinks({
manifest: 'https://cdn.example.com/manifest.m3u8',
});Available preset message classes:
| Preset | Class | Key Methods |
| ------------- | -------------------- | --------------------------------------------------------------------------------- |
| status | StatusMessage | updatePreset(), complete(), fail() |
| progress | ProgressMessage | updatePreset(), setProgressValue(), complete() |
| pipeline | PipelineMessage | updatePreset(), updateStep(), updateStepByName() |
| encodingJob | EncodingJobMessage | updatePreset(), updateFormat(), updateFormatByName(), completeWithLinks() |
BlockBuilder
Fluent builder for Slack Block Kit:
import { BlockBuilder } from 'slack-live';
const blocks = new BlockBuilder()
.header('Deployment Status')
.divider()
.progressSection({ title: 'Building', progress: 75, status: 'running' })
.sectionWithFields([
{ label: 'Environment', value: 'Production' },
{ label: 'Version', value: 'v2.1.0' },
])
.context(['Last updated: just now'])
.build();
await message.setBlocks(blocks);Progress Bar Styles
Six built-in styles:
| Style | Example |
| --------- | -------------------------- |
| blocks | [████████░░░░░░░░] 50% |
| equals | [========........] 50% |
| arrows | [>>>>>>>>--------] 50% |
| braille | ⣿⣿⣿⣿⣿⣿⣿⣿⣀⣀⣀⣀⣀⣀⣀⣀ 50% |
| minimal | 50% ━━━━━━━━━━────────── |
| emoji | 🟩🟩🟩🟩🟩⬜⬜⬜⬜⬜ 50% |
await message.setProgress(50, { style: 'emoji', width: 10 });Status Emojis
| State | Emoji |
| ----------- | ----- |
| pending | ⏳ |
| running | 🔄 |
| completed | ✅ |
| failed | ❌ |
| cancelled | ⚪ |
Lifecycle Callbacks
await client.create(
'#builds',
{ text: 'Hello' },
{
onSent: (snapshot) => console.log('Message sent:', snapshot.ts),
onUpdated: (snapshot) => console.log('Message updated'),
onCompleted: (snapshot) => console.log('Message completed'),
onFailed: (snapshot, error) => console.log('Message failed:', error),
onCancelled: (snapshot) => console.log('Message cancelled'),
}
);Slack App Setup
- Create a new Slack App at api.slack.com/apps
- Add the following Bot Token Scopes:
chat:write- Send messageschat:write.public- Send to public channels without joining
- Install the app to your workspace
- Copy the Bot User OAuth Token (starts with
xoxb-)
App Manifest
{
"display_information": {
"name": "Live Updates Bot",
"description": "Real-time progress updates"
},
"features": {
"bot_user": {
"display_name": "Live Updates",
"always_online": true
}
},
"oauth_config": {
"scopes": {
"bot": ["chat:write", "chat:write.public"]
}
}
}Contributing
See CONTRIBUTING.md for guidelines.
License
MIT - see LICENSE for details.
This library was built with the assistance of AI.
