The Smart Reply Plugin has been enhanced with new capabilities for better message management, multi-user broadcasting, and improved error handling.
The replySmart function now supports a forceNewMessage parameter that allows you to bypass the edit behavior and always send a new message.
// Normal behavior - tries to edit existing message
await ctx.replySmart('Hello World');
// Force new message - deletes old message and sends new one
await ctx.replySmart('Hello World', { forceNewMessage: true });New sendOrEditMessageToUsers function for broadcasting messages to multiple users with individual message tracking.
// Broadcast to multiple users
const userIds = [123, 456, 789];
const results = await ctx.sendOrEditMessageToUsers(
userIds,
'Game starting in 5 minutes!',
{ parse_mode: 'HTML' },
{ forceNewMessage: true }
);
// Check results
results.forEach(result => {
if (result.success) {
console.log(`Message sent to user ${result.userId}`);
} else {
console.log(`Failed to send to user ${result.userId}: ${result.error}`);
}
});The plugin now handles various error scenarios gracefully:
- Edit failures: Automatically falls back to sending new messages
- Message deletion: Attempts to delete old messages when forcing new ones
- Broadcast failures: Individual user failures don't stop other users from receiving messages
// In a game action handler
async function handleGameUpdate(ctx: GameHubContext) {
// Update game status - will edit existing message if available
await ctx.replySmart('Game status: Waiting for players...', {
reply_markup: generateGameKeyboard()
});
// Later, force a new message for important notifications
await ctx.replySmart('Game starting now!', {
forceNewMessage: true,
reply_markup: generateStartGameKeyboard()
});
}// Notify all players in a room
async function notifyRoomPlayers(ctx: GameHubContext, roomId: string) {
const players = await getRoomPlayers(roomId);
const playerIds = players.map(p => p.userId);
const results = await ctx.sendOrEditMessageToUsers(
playerIds,
'Your turn to play!',
{ parse_mode: 'HTML' },
{ forceNewMessage: true } // Force notification
);
// Log any failures
const failures = results.filter(r => !r.success);
if (failures.length > 0) {
console.log(`Failed to notify ${failures.length} players`);
}
}// Progressive game updates
async function updateGameProgress(ctx: GameHubContext) {
// First update - creates new message
await ctx.replySmart('Game started!', {
reply_markup: generateGameControls()
});
// Second update - edits the same message
await ctx.replySmart('Game started! Round 1...', {
reply_markup: generateGameControls()
});
// Third update - edits the same message
await ctx.replySmart('Game started! Round 1... Round 2...', {
reply_markup: generateGameControls()
});
// Final notification - forces new message for attention
await ctx.replySmart('Game finished! Check results below.', {
forceNewMessage: true,
reply_markup: generateResultsKeyboard()
});
}Sends or edits a message based on previous message history.
Parameters:
text: Message text to sendoptions: Optional configurationchatId?: string | number: Target chat ID (defaults to current chat)userId?: string: User ID for message tracking (defaults to current user)forceNewMessage?: boolean: Force new message instead of editing (default: false)reply_markup?: InlineKeyboardMarkup | ReplyKeyboardMarkup | ReplyKeyboardRemove | ForceReply: Keyboard markupparse_mode?: 'HTML' | 'Markdown' | 'MarkdownV2': Text parsing mode
sendOrEditMessageToUsers(userIds: number[], text: string, messageOptions?: SmartReplyOptions, broadcastOptions?: BroadcastOptions): Promise<BroadcastResult[]>
Broadcasts a message to multiple users with individual tracking.
Parameters:
userIds: Array of user IDs to send messages totext: Message text to sendmessageOptions: Message-specific optionsbroadcastOptions: Broadcast-specific options (excludes chatId and userId)
Returns:
- Array of
BroadcastResultobjects with success/failure status for each user
interface BroadcastResult {
userId: number;
success: boolean;
error?: string;
}Old way:
await ctx.broadcastToUsers(['123', '456'], 'Hello users!');New way:
const results = await ctx.sendOrEditMessageToUsers(
[123, 456],
'Hello users!'
);Before:
// Always sent new message
await ctx.replySmart('Important notification!');After:
// Can control whether to edit or force new message
await ctx.replySmart('Important notification!', { forceNewMessage: true });- Use
forceNewMessage: truefor important notifications that should grab user attention - Use normal mode for progressive updates to keep chat clean
- Handle broadcast results to log failures and retry if needed
- Use appropriate parse modes for rich text formatting
- Consider user experience - don't spam with too many forced new messages
The plugin automatically handles common error scenarios:
- Message too old to edit: Falls back to new message
- Message deleted: Attempts to delete old message, sends new one
- User blocked bot: Logs error, continues with other users
- Network errors: Retries automatically where appropriate
All errors are logged with context information for debugging.