### Initialize Chat Members Plugin with Storage Adapter Source: https://github.com/grammyjs/chat-members/blob/main/src/README.md This snippet demonstrates how to initialize the chat members plugin for a grammY bot. It requires a storage adapter (like MemorySessionStorage) and sets up the bot to use the chat members middleware. The bot is then started, listening for chat_member and message updates. ```typescript import { Bot, Context, MemorySessionStorage } from "https://deno.land/x/grammy/mod.ts"; import type { ChatMember } from "https://deno.land/x/grammy/types.ts"; import { chatMembers, ChatMembersFlavor } from "https://deno.land/x/grammy_chat_members/mod.ts"; type MyContext = Context & ChatMembersFlavor; const adapter = new MemorySessionStorage(); const bot = new Bot(""); bot.use(chatMembers(adapter)); bot.start({ allowed_updates: ["chat_member", "message"], onStart: ({ username }) => console.log(`Listening as ${username}`); }); ``` -------------------------------- ### Filter User Status Changes with chatMemberFilter (TypeScript) Source: https://context7.com/grammyjs/chat-members/llms.txt This example shows how to use `chatMemberFilter` to monitor and react to any user's status changes within a chat. This requires the bot to have administrator privileges and `chat_member` updates to be enabled. The code handles welcoming new members, detecting departures, and tracking promotions/demotions. It also demonstrates filtering for complex status transitions like bans and restrictions being lifted. ```typescript import { Bot, Context, API_CONSTANTS } from "grammy"; import { chatMemberFilter } from "@grammyjs/chat-members"; const bot = new Bot(process.env.BOT_TOKEN!); const groups = bot.chatType(["group", "supergroup"]); // Welcome new members joining the group groups.filter(chatMemberFilter("out", "in"), async (ctx) => { const user = ctx.chatMember.new_chat_member.user; await ctx.reply(`Welcome ${user.first_name} to the group!`); }); // Detect when a user leaves or is removed groups.filter(chatMemberFilter("in", "out"), async (ctx) => { const user = ctx.chatMember.new_chat_member.user; console.log(`User ${user.id} left chat ${ctx.chat.id}`); }); // Detect user promotions to admin groups.filter(chatMemberFilter("regular", "admin"), async (ctx) => { const { user } = ctx.chatMember.new_chat_member; const promotedBy = ctx.from; await ctx.reply(`${user.first_name} was promoted to admin by ${promotedBy.first_name}!`); }); // Detect user demotions groups.filter(chatMemberFilter("admin", "regular"), async (ctx) => { const { user } = ctx.chatMember.new_chat_member; await ctx.reply(`${user.first_name} is no longer an admin.`); }); // Detect ban/restriction changes using array queries groups.filter( chatMemberFilter(["restricted", "kicked"], ["free", "left"]), async (ctx) => { const { status: oldStatus, user } = ctx.chatMember.old_chat_member; await ctx.reply( `${oldStatus === "kicked" ? "Ban" : "Restrictions"} lifted from ${user.first_name}` ); } ); bot.start({ allowed_updates: [...API_CONSTANTS.DEFAULT_UPDATE_TYPES, "chat_member"], onStart: (me) => console.log(`Bot @${me.username} started`) }); ``` -------------------------------- ### Read Chat Member Info using Context (TypeScript) Source: https://github.com/grammyjs/chat-members/blob/main/README.md This example shows how to retrieve chat member information within a grammY bot's message handler. It uses `ctx.chatMembers.getChatMember()` which first checks the configured storage and falls back to the Telegram API if the data is not found, caching it for future use. ```typescript bot.on("message", async (ctx) => { const chatMember = await ctx.chatMembers.getChatMember(); await ctx.reply(`Hello, ${chatMember.user.first_name}! I see you are a ${chatMember.status} of this chat!`); }); ``` -------------------------------- ### Chat Member Status Query Types Reference Source: https://context7.com/grammyjs/chat-members/llms.txt This TypeScript code provides a reference for chat member status query types used within the @grammyjs/chat-members plugin. It defines standard Telegram statuses and extended query types like 'in', 'out', 'free', 'admin', 'regular', 'restricted_in', and 'restricted_out'. An example transition table for groups is included to aid in planning filter handlers. ```typescript // Standard Telegram statuses type TelegramStatus = | "administrator" // Chat administrator | "creator" // Chat owner | "member" // Regular member | "restricted" // Member with restrictions (ambiguous - in or out) | "left" // User left the chat | "kicked"; // User was banned // Extended status queries provided by the plugin type ExtendedQuery = | "in" // Any member: administrator | creator | member | restricted_in | "out" // Not a member: left | kicked | restricted_out | "free" // Member without restrictions: administrator | creator | member | "admin" // Administrator: administrator | creator | "regular" // Non-admin member: member | restricted_in | "restricted_in" // Restricted but is_member: true | "restricted_out";// Restricted but is_member: false // Example transition table for groups // Use this to plan your filter handlers: // // | From \ To | Out | Regular | Admin | // |-------------|-------------|----------------------|---------------------| // | Out | ban-changed | user-joined | join-and-promoted | // | Regular | user-left | restrictions-changed | user-promoted | // | Admin | admin-left | admin-demoted | permissions-changed | ``` -------------------------------- ### Filter Bot Status Changes with myChatMemberFilter (TypeScript) Source: https://context7.com/grammyjs/chat-members/llms.txt This code snippet demonstrates how to use `myChatMemberFilter` to react to changes in the bot's own status within a chat. It covers scenarios like being added, promoted, demoted, or removed from a group. Ensure you have the grammY library and the `@grammyjs/chat-members` package installed. ```typescript import { Bot, Context } from "grammy"; import { myChatMemberFilter } from "@grammyjs/chat-members"; const bot = new Bot(process.env.BOT_TOKEN!); const groups = bot.chatType(["group", "supergroup"]); // React when bot is added to a group (was out, now in) groups.filter(myChatMemberFilter("out", "in"), async (ctx) => { await ctx.reply("Hello! Thanks for adding me to the group!"); }); // React when bot is promoted to admin groups.filter(myChatMemberFilter("regular", "admin"), async (ctx) => { await ctx.reply("Thank you for promoting me to admin!"); }); // React when bot is demoted from admin groups.filter(myChatMemberFilter("admin", "regular"), async (ctx) => { await ctx.reply("I'm no longer an admin in this group."); }); // React when bot is removed from group groups.filter(myChatMemberFilter("in", "out"), async (ctx) => { console.log(`Bot was removed from chat ${ctx.chat.id}`); }); bot.start({ onStart: (me) => console.log(`Bot @${me.username} started`) }); ``` -------------------------------- ### Initialize Chat Members Plugin with Storage Adapter (TypeScript) Source: https://github.com/grammyjs/chat-members/blob/main/README.md This snippet demonstrates how to initialize the chat members plugin for a grammY bot. It requires a storage adapter (like MemorySessionStorage) and sets up the bot to listen for chat member and message updates. ```typescript import { Bot, Context, MemorySessionStorage } from "grammy"; import type { ChatMember } from "@grammyjs/types"; import { chatMembers, ChatMembersFlavor } from "@grammyjs/chat-members"; type MyContext = Context & ChatMembersFlavor; const adapter = new MemorySessionStorage(); const bot = new Bot(""); bot.use(chatMembers(adapter)); bot.start({ allowed_updates: ["chat_member", "message"], onStart: ({ username }) => console.log(`Listening as ${username}`), }); ``` -------------------------------- ### Process All Chat Member Updates with Middleware (TypeScript) Source: https://github.com/grammyjs/chat-members/blob/main/README.md Illustrates how to use a general `on('chat_member')` middleware to process all chat member updates before specific handlers. This is useful for common tasks like logging or updating a database with the status change information. ```typescript const groups = bot.chatType(["group", "supergroup"]); groups.on("chat_member", (ctx, next) => { // ran on all updates of type chat_member const { old_chat_member: { status: oldStatus }, new_chat_member: { user, status }, from, chat, } = ctx.chatMember; console.log( `In group ${chat.id} user ${from.id} changed status of ${user.id}:`, `${oldStatus} -> ${status}`, ); // update database data here await next(); }); // specific handlers groups.filter(chatMemberFilter("out", "in"), async (ctx, next) => { const { new_chat_member: { user } } = ctx.chatMember; await ctx.reply(`Welcome ${user.first_name}!`); }); ``` -------------------------------- ### Manage Chat Members with Middleware (TypeScript) Source: https://context7.com/grammyjs/chat-members/llms.txt The `chatMembers` middleware automatically stores and manages chat member information using a provided storage adapter. It can be configured to keep records of users who left, enable caching, and customize the key strategy for storage. This middleware enhances the context with `ChatMembersFlavor`. ```typescript import { Bot, Context, MemorySessionStorage } from "grammy"; import type { ChatMember } from "@grammyjs/types"; import { chatMembers, ChatMembersFlavor } from "@grammyjs/chat-members"; type MyContext = Context & ChatMembersFlavor; const bot = new Bot(process.env.BOT_TOKEN!); // Use in-memory storage (for production, use a persistent adapter) const adapter = new MemorySessionStorage(); // Basic usage - stores members automatically on chat_member updates bot.use(chatMembers(adapter)); // With configuration options bot.use(chatMembers(adapter, { // Keep records of users who left (default: false - deletes them) keepLeftChatMembers: true, // Enable caching to reduce storage reads (default: false, true if aggressive) enableCaching: true, // Custom key strategy (default: `${chatId}_${userId}`) getKey: (chatId, userId) => `${chatId}_${userId}`, })); bot.on("message", async (ctx) => { const chatMember = await ctx.chatMembers.getChatMember(); await ctx.reply(`Hello ${chatMember.user.first_name}! You are a ${chatMember.status}.`); }); bot.start({ allowed_updates: ["chat_member", "message"], onStart: ({ username }) => console.log(`Bot @${username} started`), }); ``` -------------------------------- ### Handle Chat Member Status Changes with Filters (TypeScript) Source: https://github.com/grammyjs/chat-members/blob/main/README.md Demonstrates how to use custom filters like `myChatMemberFilter` and `chatMemberFilter` to react to various chat member status transitions in grammY. It covers scenarios such as a bot being added to a group, promoted to admin, or users joining/leaving. Requires the 'chat_member' update type to be enabled. ```typescript const bot = new Bot(process.env.BOT_TOKEN!); const groups = bot.chatType(["group", "supergroup"]); groups.filter(myChatMemberFilter("out", "regular"), async (ctx) => { await ctx.reply("Hello, thank you for adding me to the group!"); }); groups.filter(myChatMemberFilter("out", "admin"), async (ctx) => { await ctx.reply("Hello, thank you for adding me to the group as admin!"); }); groups.filter(myChatMemberFilter("regular", "admin"), async (ctx) => { await ctx.reply("I was promoted to admin!"); }); groups.filter(myChatMemberFilter("admin", "regular"), async (ctx) => { await ctx.reply("I am no longer admin"); }); groups.filter(chatMemberFilter("out", "in"), async (ctx) => { const user = ctx.chatMember.new_chat_member.user; await ctx.reply( `Welcome ${escapeHtml(user.first_name)} to the group!`, { parse_mode: "HTML" }, ); }); bot.start({ allowed_updates: [...API_CONSTANTS.DEFAULT_UPDATE_TYPES, "chat_member"], onStart: (me) => console.log("Listening to updates as", me.username), }); ``` -------------------------------- ### Create Custom Chat Member Status Groupings (TypeScript) Source: https://github.com/grammyjs/chat-members/blob/main/README.md Shows how to define custom groupings of chat member statuses by passing arrays to `chatMemberFilter`. This allows for more granular control over which transitions trigger a response, such as combining 'restricted' and 'kicked' statuses. ```typescript groups.filter( chatMemberFilter(["restricted", "kicked"], ["free", "left"]), async (ctx) => { const from = ctx.from; const { status: oldStatus, user } = ctx.chatMember.old_chat_member; await ctx.reply( `${escapeHtml(from.first_name)} lifted ` + `${oldStatus === "kicked" ? "ban" : "restrictions"} ` + `from ${escapeHtml(user.first_name)}`, { parse_mode: "HTML" }, ); }, ); ``` -------------------------------- ### Enable Aggressive Storage for Chat Members Source: https://context7.com/grammyjs/chat-members/llms.txt This snippet demonstrates how to enable aggressive storage mode in the @grammyjs/chat-members plugin. Aggressive storage automatically caches chat member data on every update, not just specific `chat_member` events. This can increase storage operations and should be used with caution. It requires a Bot instance and a session storage adapter. ```typescript import { Bot, Context, MemorySessionStorage, } from "grammy"; import type { ChatMember } from "@grammyjs/types"; import { chatMembers, ChatMembersFlavor, } from "@grammyjs/chat-members"; type MyContext = Context & ChatMembersFlavor; const bot = new Bot(process.env.BOT_TOKEN!); const adapter = new MemorySessionStorage(); // Enable aggressive storage - caches member info on every update bot.use(chatMembers(adapter, { enableAggressiveStorage: true, // Caches on every update with ctx.chat and ctx.from // enableCaching is automatically true when aggressive storage is enabled })); // Now every message automatically stores the sender's chat member info bot.on("message", async (ctx) => { // Member info was already cached by the aggressive storage middleware const member = await ctx.chatMembers.getChatMember(); // This call returns from cache/storage without hitting Telegram API console.log(`Cached member: ${member.user.first_name} (${member.status})`); }); bot.start({ allowed_updates: ["message"] }); ``` -------------------------------- ### Hydrate Chat Member API Transformer with .is() Method Source: https://context7.com/grammyjs/chat-members/llms.txt This code snippet shows how to use the `hydrateChatMember` API transformer from the @grammyjs/chat-members plugin. This transformer adds a convenient `.is()` method to `ChatMember` objects obtained via methods like `getChatMember`, `getChatAdministrators`, and `getAuthor`. The `.is()` method allows for easy checking of a member's status (e.g., 'admin', 'restricted', 'member'). ```typescript import { Bot, Context } from "grammy"; import { hydrateChatMember, HydrateChatMemberFlavor, } from "@grammyjs/chat-members"; type MyContext = HydrateChatMemberFlavor; const bot = new Bot(process.env.BOT_TOKEN!); // Install the API transformer bot.api.config.use(hydrateChatMember()); bot.on("message", async (ctx) => { // getAuthor returns a hydrated ChatMember with .is() method const author = await ctx.getAuthor(); if (author.is("admin")) { // TypeScript narrows type to ChatMemberAdmin await ctx.reply(`You're an admin with status: ${author.status}`); } else if (author.is("restricted")) { await ctx.reply("You have some restrictions in this chat."); } else if (author.is("member")) { await ctx.reply("You're a regular member."); } }); bot.command("admins", async (ctx) => { const admins = await ctx.getChatAdministrators(); for (const admin of admins) { if (admin.is("creator")) { await ctx.reply(`Owner: ${admin.user.first_name}`); } else if (admin.is("administrator")) { await ctx.reply(`Admin: ${admin.user.first_name}`); } } }); bot.command("checkuser", async (ctx) => { const userId = ctx.message.reply_to_message?.from?.id; if (!userId) return; const member = await ctx.getChatMember(userId); if (member.is("out")) { await ctx.reply("This user is not in the chat."); } else if (member.is("free")) { await ctx.reply("This user has no restrictions."); } else if (member.is("restricted_in")) { await ctx.reply("This user is restricted but still a member."); } }); bot.start(); ``` -------------------------------- ### Retrieve Chat Member Info with ctx.chatMembers.getChatMember (TypeScript) Source: https://context7.com/grammyjs/chat-members/llms.txt The `ctx.chatMembers.getChatMember()` method retrieves chat member information, first checking the storage adapter and then falling back to the Telegram API if the data is not found. It can retrieve the current user's info in the current chat, a specific user's info in the current chat, or a user's info from a different chat. ```typescript import { Bot, Context, MemorySessionStorage } from "grammy"; import type { ChatMember } from "@grammyjs/types"; import { chatMembers, ChatMembersFlavor } from "@grammyjs/chat-members"; type MyContext = Context & ChatMembersFlavor; const bot = new Bot(process.env.BOT_TOKEN!); const adapter = new MemorySessionStorage(); bot.use(chatMembers(adapter)); // Get current user in current chat (uses ctx.chat.id and ctx.from.id) bot.on("message", async (ctx) => { const member = await ctx.chatMembers.getChatMember(); console.log(`User ${member.user.id} has status: ${member.status}`); }); // Get specific user in current chat bot.command("check", async (ctx) => { const userId = ctx.message.reply_to_message?.from?.id; if (userId) { const member = await ctx.chatMembers.getChatMember(undefined, userId); await ctx.reply(`User status: ${member.status}`); } }); // Get user from a different chat bot.command("crosscheck", async (ctx) => { const otherChatId = -1001234567890; const member = await ctx.chatMembers.getChatMember(otherChatId, ctx.from.id); await ctx.reply(`Your status in the other chat: ${member.status}`); }); bot.start({ allowed_updates: ["chat_member", "message"] }); ``` -------------------------------- ### Enable Aggressive Chat Member Storage Caching Source: https://github.com/grammyjs/chat-members/blob/main/src/README.md This configuration option, `enableAggressiveStorage`, caches chat members without relying on the `chat_member` event. It intercepts every update, checks for `ctx.chat` and `ctx.from`, and calls `ctx.chatMembers.getChatMember` if necessary. Use with caution due to potential performance impacts. ```typescript // Example usage within bot setup (assuming adapter and bot are already defined): // bot.use(chatMembers(adapter, { enableAggressiveStorage: true })); /* Note: The actual code for enabling aggressive storage is typically passed as an option during the `chatMembers` middleware setup. This snippet is illustrative of the concept. const adapter = new MemorySessionStorage(); const bot = new Bot(""); bot.use(chatMembers(adapter, { enableAggressiveStorage: true })); */ ``` -------------------------------- ### Check Chat Member Status with chatMemberIs (TypeScript) Source: https://context7.com/grammyjs/chat-members/llms.txt The `chatMemberIs` utility function checks the status of a chat member. It returns a type guard for safe access to member properties based on their status. It supports checking against single statuses, multiple statuses, or predefined convenience groups like 'admin' or 'in'. ```typescript import { chatMemberIs } from "@grammyjs/chat-members"; import type { ChatMember } from "@grammyjs/types"; // Check if a chat member is an admin (creator or administrator) function checkAdminStatus(member: ChatMember): void { if (chatMemberIs(member, "admin")) { // TypeScript knows member is ChatMemberAdmin here console.log(`User is an admin with status: ${member.status}`); } } // Check if member is in the chat function checkMembership(member: ChatMember): void { if (chatMemberIs(member, "in")) { console.log("User is a member of this chat"); } else if (chatMemberIs(member, "out")) { console.log("User is not in this chat"); } } // Use with multiple query values function checkFreeOrAdmin(member: ChatMember): void { if (chatMemberIs(member, ["free", "admin"])) { console.log("User has no restrictions and/or is an admin"); } } // Available status queries: // - Telegram statuses: "administrator", "creator", "kicked", "left", "member", "restricted" // - Convenience groups: "in", "out", "free", "admin", "regular", "restricted_in", "restricted_out" ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.