### Deno Quickstart Source: https://github.com/grammyjs/website/blob/main/site/docs/README.md Set up a basic Telegram bot using grammY in Deno. This example shows how to import grammY and start a bot that replies to messages. ```typescript import { Bot } from "https://deno.land/x/grammy/mod.ts"; const bot = new Bot(""); // <-- put your bot token between the "" (https://t.me/BotFather) // Reply to any message with "Hi there!". bot.on("message", (ctx) => ctx.reply("Hi there!")); bot.start(); ``` -------------------------------- ### Create and Run a Basic Deno Bot with Grammy.js Source: https://github.com/grammyjs/website/blob/main/site/docs/guide/getting-started.md This snippet demonstrates the initial setup for a Deno bot using the Grammy.js library. It includes creating a bot instance, registering handlers for the '/start' command and general messages, and starting the bot. It requires a bot token from BotFather and specific Deno runtime permissions. ```shell mkdir ./my-bot cd ./my-bot touch bot.ts ``` ```typescript import { Bot } from "https://deno.land/x/grammy/mod.ts"; // Create an instance of the `Bot` class and pass your bot token to it. const bot = new Bot(""); // <-- put your bot token between the "" // You can now register listeners on your bot object `bot`. // grammY will call the listeners when users send messages to your bot. // Handle the /start command. bot.command("start", (ctx) => ctx.reply("Welcome! Up and running.")); // Handle other messages. bot.on("message", (ctx) => ctx.reply("Got another message!")); // Now that you specified how to handle messages, you can start your bot. // This will connect to the Telegram servers and wait for messages. // Start the bot. bot.start(); ``` ```shell deno -IN bot.ts ``` -------------------------------- ### Free Cloud Storage Setup (Deno) Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/session.md Integrate the free cloud storage adapter for persistent sessions using Deno. This example shows the import path for Deno. ```typescript import { freeStorage } from "https://deno.land/x/grammy_storages/free/src/mod.ts"; bot.use(session({ initial: ... storage: freeStorage(bot.token), })); ``` -------------------------------- ### Quickstart: Basic Conversation Flow Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/conversations.md This example demonstrates a basic conversation flow where the bot asks for the user's name and then replies with a welcome message. It requires importing necessary modules and setting up the bot with the conversations plugin. The `createConversation` function is used to define the conversation logic, and `ctx.conversation.enter` is used to initiate it. ```TypeScript import { Bot, type Context, } from "grammy"; import { type Conversation, type ConversationFlavor, conversations, createConversation, } from "@grammyjs/conversations"; const bot = new Bot>(""); // <-- put your bot token between the "" (https://t.me/BotFather) bot.use(conversations()); /** Defines the conversation */ async function hello(conversation: Conversation, ctx: Context) { await ctx.reply("Hi there! What is your name?"); const { message } = await conversation.waitFor("message:text"); await ctx.reply(`Welcome to the chat, ${message.text}!`); } bot.use(createConversation(hello)); bot.command("enter", async (ctx) => { // Enter the function "hello" you declared. await ctx.conversation.enter("hello"); }); bot.start(); ``` ```JavaScript const { Bot } = require("grammy"); const { conversations, createConversation } = require( "@grammyjs/conversations", ); const bot = new Bot(""); // <-- put your bot token between the "" (https://t.me/BotFather) bot.use(conversations()); /** Defines the conversation */ async function hello(conversation, ctx) { await ctx.reply("Hi there! What is your name?"); const { message } = await conversation.waitFor("message:text"); await ctx.reply(`Welcome to the chat, ${message.text}!`); } bot.use(createConversation(hello)); bot.command("enter", async (ctx) => { // Enter the function "hello" you declared. await ctx.conversation.enter("hello"); }); bot.start(); ``` ```Deno import { Bot, type Context, } from "https://deno.land/x/grammy/mod.ts"; import { type Conversation, type ConversationFlavor, conversations, createConversation, } from "https://deno.land/x/grammy_conversations/mod.ts"; const bot = new Bot>(""); // <-- put your bot token between the "" (https://t.me/BotFather) bot.use(conversations()); /** Defines the conversation */ async function hello(conversation: Conversation, ctx: Context) { await ctx.reply("Hi there! What is your name?"); const { message } = await conversation.waitFor("message:text"); await ctx.reply(`Welcome to the chat, ${message.text}!`); } bot.use(createConversation(hello)); bot.command("enter", async (ctx) => { // Enter the function "hello" you declared. await ctx.conversation.enter("hello"); }); bot.start(); ``` -------------------------------- ### Free Cloud Storage Setup (JavaScript) Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/session.md Integrate the free cloud storage adapter for persistent sessions using JavaScript. Ensure you have installed the `@grammyjs/storage-free` package. ```javascript const { freeStorage } = require("@grammyjs/storage-free"); bot.use(session({ initial: ... storage: freeStorage(bot.token), })); ``` -------------------------------- ### Initialize Project and Install Dependencies Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/zeabur-nodejs.md Sets up a new Node.js project, installs grammY, and adds TypeScript development dependencies. ```sh # Initialize the project. mkdir grammy-bot cd grammy-bot npm init -y # Install main dependencies. npm install grammy # Install development dependencies. npm install -D typescript ts-node @types/node # Initialize TypeScript. npx tsc --init ``` -------------------------------- ### Free Cloud Storage Setup (TypeScript) Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/session.md Integrate the free cloud storage adapter for persistent sessions using TypeScript. Ensure you have installed the `@grammyjs/storage-free` package. ```typescript import { freeStorage } from "@grammyjs/storage-free"; bot.use(session({ initial: ... storage: freeStorage(bot.token), })); ``` -------------------------------- ### Install Grammy.js on Node.js using npm, Yarn, or pnpm Source: https://github.com/grammyjs/website/blob/main/site/docs/guide/getting-started.md Installs the grammy package and sets up a new TypeScript project. Assumes Node.js and npm are installed. This is a prerequisite for creating a bot. ```sh # Create a new directory and change into it. mkdir my-bot cd my-bot # Set up TypeScript (skip if you use JavaScript). npm install -D typescript npx tsc --init # Install grammY. npm install grammy ``` ```sh # Create a new directory and change into it. mkdir my-bot cd my-bot # Set up TypeScript (skip if you use JavaScript). yarn add typescript -D npx tsc --init # Install grammY. yarn add grammy ``` ```sh # Create a new directory and change into it. mkdir my-bot cd my-bot # Set up TypeScript (skip if you use JavaScript). pnpm add -D typescript pnpm exec tsc --init # Install grammY. pnpm add grammy ``` -------------------------------- ### Install Entity Parser with Deno Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/entity-parser.md Install the entity-parser package using Deno. ```sh deno add jsr:@qz/telegram-entities-parser ``` -------------------------------- ### Install Entity Parser with Bun Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/entity-parser.md Install the entity-parser package using Bun. ```sh bunx jsr add @qz/telegram-entities-parser ``` -------------------------------- ### Fluent Translation File Example (English) Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/i18n.md An example of an English translation file in the Fluent (.ftl) format. It defines messages for 'start' and 'help' commands. ```ftl start = Hi, how can I /help you? help = Send me some text, and I can make it bold for you. You can change my language using the /language command. ``` -------------------------------- ### Install Entity Parser with Yarn Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/entity-parser.md Install the entity-parser package using Yarn. ```sh yarn dlx jsr add @qz/telegram-entities-parser ``` -------------------------------- ### Full Bot Example with Free Storage (Deno) Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/session.md A complete bot example demonstrating the use of grammY's session middleware with the free cloud storage adapter in Deno. It includes session data definition and a basic message handler. ```typescript import { Bot, Context, session, SessionFlavor, } from "https://deno.land/x/grammy/mod.ts"; import { freeStorage } from "https://deno.land/x/grammy_storages/free/src/mod.ts"; // Define the session structure. interface SessionData { count: number; } type MyContext = Context & SessionFlavor; // Create the bot and register the session middleware. const bot = new Bot(""); bot.use( session({ initial: () => ({ count: 0 }), storage: freeStorage(bot.token), }), ); // Use persistent session data in update handlers. bot.on("message", async (ctx) => { ctx.session.count++; await ctx.reply(`Message count: ${ctx.session.count}`); }); bot.catch((err) => console.error(err)); bot.start(); ``` -------------------------------- ### Install Entity Parser with npm Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/entity-parser.md Install the entity-parser package using npm. ```sh npx jsr add @qz/telegram-entities-parser ``` -------------------------------- ### Configure npm start script Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/zeabur-nodejs.md Adds a 'start' script to package.json for running the TypeScript bot using ts-node. This is essential for deployment. ```json { "name": "telegram-bot-starter", "version": "1.0.0", "description": "Telegram Bot Starter with TypeScript and grammY", "scripts": { "start": "ts-node src/bot.ts" // [!code focus] }, "author": "MichaelYuhe", "license": "MIT", "dependencies": { "grammy": "^1.21.1" }, "devDependencies": { "@types/node": "^20.14.5", "ts-node": "^10.9.2", "typescript": "^5.4.5" } } ``` -------------------------------- ### Install Menu Plugin Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/menu.md This code demonstrates how to install the menu plugin into your grammY bot instance using `bot.use()`. ```typescript bot.use(menu); ``` -------------------------------- ### Install Entity Parser with pnpm Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/entity-parser.md Install the entity-parser package using pnpm. ```sh pnpm dlx jsr add @qz/telegram-entities-parser ``` -------------------------------- ### Start Development Server Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/cloudflare-workers-nodejs.md Run this command in your terminal to start the local development server for your Cloudflare Workers bot. ```sh npm run dev ``` -------------------------------- ### Implement and Install Response Time Middleware (JavaScript) Source: https://github.com/grammyjs/website/blob/main/site/docs/guide/middleware.md Provides the complete implementation of the `responseTime` middleware in JavaScript. It records the time before and after invoking the next middleware, then logs the difference. The middleware is installed using `bot.use()`. ```javascript /** Measures the response time of the bot, and logs it to `console` */ async function responseTime(ctx, next) { // take time before const before = Date.now(); // milliseconds // invoke downstream middleware await next(); // make sure to `await`! // take time after const after = Date.now(); // milliseconds // log difference console.log(`Response time: ${after - before} ms`); } bot.use(responseTime); ``` -------------------------------- ### Install Caddy Web Server Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/vps.md Installs the Caddy web server on Debian-based systems using apt. This process involves adding the Caddy repository and then installing the caddy package. It ensures the web server is ready to be configured. ```shell apt install -y debian-keyring debian-archive-keyring apt-transport-https curl curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list apt update apt install caddy ``` -------------------------------- ### Install Emoji Plugin (Deno) Source: https://github.com/grammyjs/website/blob/main/site/docs/zh/plugins/emoji.md Install the emoji plugin for Deno projects. This involves importing necessary components and using the emojiParser middleware. ```typescript import { Bot, Context } from "https://deno.land/x/grammy/mod.ts"; import { EmojiFlavor, emojiParser, } from "https://deno.land/x/grammy_emoji/mod.ts"; // 这个被称为上下文调味剂 // 你可以在这里阅读更多关于它们的信息: // https://grammy.dev/zh/guide/context#转换式上下文调味剂 type MyContext = EmojiFlavor; const bot = new Bot(""); bot.use(emojiParser()); ``` -------------------------------- ### Deno Session Example Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/session.md Example bot that counts pizza emojis using session data in Deno. Requires session middleware and context flavor. ```typescript import { Bot, Context, session, SessionFlavor, } from "https://deno.land/x/grammy/mod.ts"; // Define shape of our session. interface SessionData { pizzaCount: number; } // Flavor the context type to include sessions. type MyContext = Context & SessionFlavor; const bot = new Bot(""); // Install session middleware, and define the initial session value. function initial(): SessionData { return { pizzaCount: 0 }; } bot.use(session({ initial })); bot.command("hunger", async (ctx) => { const count = ctx.session.pizzaCount; await ctx.reply(`Your hunger level is ${count}!`); }); bot.hears(/.*🍕.*/, (ctx) => ctx.session.pizzaCount++); bot.start(); ``` -------------------------------- ### Session Key Examples in JavaScript Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/session.md Provides JavaScript implementations for session key resolvers, mirroring the TypeScript examples for per chat, per user, and per user-chat scoping. This allows for flexible session management in JavaScript environments. ```javascript // Stores data per chat (default). function getSessionKey(ctx) { // Let all users in a group chat share the same session, // but give an independent private one to each user in private chats return ctx.chat?.id.toString(); } // Stores data per user. function getSessionKey(ctx) { // Give every user their personal session storage // (will be shared across groups and in their private chat) return ctx.from?.id.toString(); } // Stores data per user-chat combination. function getSessionKey(ctx) { // Give every user their one personal session storage per chat with the bot // (an independent session for each group and their private chat) return ctx.from === undefined || ctx.chat === undefined ? undefined : `${ctx.from.id}/${ctx.chat.id}`; } bot.use(session({ getSessionKey })); ``` -------------------------------- ### Fluent Translation File Example (German) Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/i18n.md An example of a German translation file in the Fluent (.ftl) format, corresponding to the English example. It provides translations for 'start' and 'help' commands. ```ftl start = Hallo, wie kann ich dir helfen? /help help = Schick eine Textnachricht, die ich für dich fett schreiben soll. Du kannst mit dem Befehl /language die Spache ändern. ``` -------------------------------- ### Initialize Deno project structure Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/zeabur-deno.md Commands to create the project directory and necessary files for a Deno-based grammY bot. ```sh # Initialize the project. mkdir grammy-bot cd grammy-bot # Create main.ts file touch main.ts # Create deno.json file to generate lock file touch deno.json ``` -------------------------------- ### Compile and run a Grammy.js bot on Node.js Source: https://github.com/grammyjs/website/blob/main/site/docs/guide/getting-started.md Compiles the TypeScript bot code into JavaScript and then runs the bot using Node.js. This is the final step to get your bot online. ```sh # Compile the TypeScript code npx tsc # Run the bot node bot.js ``` -------------------------------- ### Complete Game Integration Example Source: https://github.com/grammyjs/website/blob/main/site/docs/guide/games.md Combines listening for game button presses and sending a game with an inline keyboard. This example demonstrates a basic setup for integrating a Telegram game into your bot. ```typescript bot.on("callback_query:game_short_name", async (ctx) => { await ctx.answerCallbackQuery({ url: "your_game_url" }); }); bot.command("start", async (ctx) => { await ctx.replyWithGame("my_game", { reply_markup: keyboard, // Or you can use the api method here, according to your needs. }); }); ``` -------------------------------- ### Basic Session Setup Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/session.md This snippet shows the basic structure for setting up session middleware with a custom storage adapter. ```typescript const storageAdapter = ... // depends on setup bot.use(session({ initial: ... storage: storageAdapter, })); ``` -------------------------------- ### Example Grammy.js Bot for Firebase Functions Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/firebase.md A basic Grammy.js bot example designed to be deployed as a Firebase Function. It includes simple 'start' and 'ping' commands and exports the bot as an HTTPS callable function. ```typescript import * as functions from "firebase-functions"; import { Bot, webhookCallback } from "grammy"; const bot = new Bot(""); bot.command("start", (ctx) => ctx.reply("Welcome! Up and running.")); bot.command("ping", (ctx) => ctx.reply(`Pong! ${new Date()}`)); // During development, you can trigger your function from https://localhost//us-central1/helloWorld export const helloWorld = functions.https.onRequest(webhookCallback(bot)); ``` -------------------------------- ### Create and Initialize Deno Bot Project Source: https://github.com/grammyjs/website/blob/main/site/docs/guide/introduction.md This snippet demonstrates how to create a new directory for your bot project, navigate into it, and initialize it as a Deno project using VS Code commands. It assumes you have Deno installed and the 'code' command available in your PATH. ```shell mkdir ./my-bot cd ./my-bot code . ``` -------------------------------- ### Create systemd Service File Source: https://github.com/grammyjs/website/blob/main/site/docs/zh/hosting/vps.md This is a template for a systemd service file. Replace `` with the absolute path to your bot's directory and `` with the command to start your bot. ```text [Unit] After=network.target [Service] WorkingDirectory= ExecStart= Restart=on-failure [Install] WantedBy=multi-user.target ``` -------------------------------- ### Enable debug logging for Grammy.js Source: https://github.com/grammyjs/website/blob/main/site/docs/guide/getting-started.md Sets an environment variable to enable verbose logging for the grammy library. This is useful for debugging issues with your bot. ```sh export DEBUG="grammy*" ``` -------------------------------- ### Full Bot Example with Free Storage (JavaScript) Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/session.md A complete bot example demonstrating the use of grammY's session middleware with the free cloud storage adapter in JavaScript. It includes session data definition and a basic message handler. ```javascript const { Bot, session } = require("grammy"); const { freeStorage } = require("@grammyjs/storage-free"); // Create the bot and register the session middleware. const bot = new Bot(""); bot.use( session({ initial: () => ({ count: 0 }), storage: freeStorage(bot.token), }), ); // Use persistent session data in update handlers. bot.on("message", async (ctx) => { ctx.session.count++; await ctx.reply(`Message count: ${ctx.session.count}`); }); bot.catch((err) => console.error(err)); bot.start(); ``` -------------------------------- ### Full Bot Example with Free Storage (TypeScript) Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/session.md A complete bot example demonstrating the use of grammY's session middleware with the free cloud storage adapter in TypeScript. It includes session data definition and a basic message handler. ```typescript import { Bot, Context, session, SessionFlavor } from "grammy"; import { freeStorage } from "@grammyjs/storage-free"; // Define the session structure. interface SessionData { count: number; } type MyContext = Context & SessionFlavor; // Create the bot and register the session middleware. const bot = new Bot(""); bot.use( session({ initial: () => ({ count: 0 }), storage: freeStorage(bot.token), }), ); // Use persistent session data in update handlers. bot.on("message", async (ctx) => { ctx.session.count++; await ctx.reply(`Message count: ${ctx.session.count}`); }); bot.catch((err) => console.error(err)); bot.start(); ``` -------------------------------- ### Get Runtime Path (Deno/Node.js) Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/vps.md Determines the absolute path to the Deno or Node.js runtime executable on the server. This is used to construct the start command for the bot service. ```shell which deno ``` ```shell which node ``` -------------------------------- ### Installing Error Boundaries with bot.errorBoundary Source: https://github.com/grammyjs/website/blob/main/site/docs/guide/errors.md This example shows how to use `bot.errorBoundary` to fence a composer instance and its middlewares. The `boundaryHandler` will catch errors from middlewares `Q`, `X`, `Y`, and `Z`. The `errorHandler` catches errors from `A`, `B`, `C`, and `D`. ```typescript const bot = new Bot(""); bot.use(/* A */); bot.use(/* B */); const composer = new Composer(); composer.use(/* X */); composer.use(/* Y */); composer.use(/* Z */); bot.errorBoundary(boundaryHandler /* , Q */).use(composer); bot.use(/* C */); bot.use(/* D */); bot.catch(errorHandler); function boundaryHandler(err: BotError, next: NextFunction) { console.error("Error in Q, X, Y, or Z!", err); /* * You could call `next` if you want to run * the middleware at C in case of an error: */ // await next() } function errorHandler(err: BotError) { console.error("Error in A, B, C, or D!", err); } ``` -------------------------------- ### Create a basic Grammy.js bot in TypeScript or JavaScript Source: https://github.com/grammyjs/website/blob/main/site/docs/guide/getting-started.md A simple bot that responds to the /start command and any other messages. Requires a bot token from BotFather. The code can be used in either TypeScript or JavaScript environments. ```typescript import { Bot } from "grammy"; // Create an instance of the `Bot` class and pass your bot token to it. const bot = new Bot(""); // <-- put your bot token between the "" // You can now register listeners on your bot object `bot`. // grammY will call the listeners when users send messages to your bot. // Handle the /start command. bot.command("start", (ctx) => ctx.reply("Welcome! Up and running.")); // Handle other messages. bot.on("message", (ctx) => ctx.reply("Got another message!")); // Now that you specified how to handle messages, you can start your bot. // This will connect to the Telegram servers and wait for messages. // Start the bot. bot.start(); ``` ```javascript const { Bot } = require("grammy"); // Create an instance of the `Bot` class and pass your bot token to it. const bot = new Bot(""); // <-- put your bot token between the "" // You can now register listeners on your bot object `bot`. // grammY will call the listeners when users send messages to your bot. // Handle the /start command. bot.command("start", (ctx) => ctx.reply("Welcome! Up and running.")); // Handle other messages. bot.on("message", (ctx) => ctx.reply("Got another message!")); // Now that you specified how to handle messages, you can start your bot. // This will connect to the Telegram servers and wait for messages. // Start the bot. bot.start(); ``` -------------------------------- ### Enable Debug Logging for Grammy.js Bot in Deno Source: https://github.com/grammyjs/website/blob/main/site/docs/guide/getting-started.md This snippet shows how to enable debug logging for a Grammy.js bot running on Deno. It involves setting the DEBUG environment variable before running the bot and then executing the bot with additional permissions to allow environment variable access. ```shell export DEBUG="grammy*" deno -EIN bot.ts ``` -------------------------------- ### Handle Login from Inline Query Button Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/inline-query.md This code snippet handles the `/start` command when a user initiates it from an inline query button. It checks the `start_parameter` and replies with a message and a switch inline button to return the user. ```typescript bot .command("start") .filter((ctx) => ctx.match === "login", async (ctx) => { // User is coming from inline query results. await ctx.reply("DM open, you can go back now!", { reply_markup: new InlineKeyboard() .switchInline("Go back"), }); }); ``` -------------------------------- ### Birthday Bot Setup with Grammy.js and Deno (TypeScript) Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/router.md This TypeScript code sets up a Grammy.js bot using Deno. It includes necessary imports for the Bot, Context, Keyboard, session, and Router. It defines the session data structure and initializes the bot with session middleware and command handlers for starting the bot and initiating the birthday query. ```typescript import { Bot, Context, Keyboard, session, SessionFlavor, } from "https://deno.land/x/grammy/mod.ts"; import { Router } from "https://deno.land/x/grammy_router/router.ts"; interface SessionData { step: "idle" | "day" | "month"; // which step of the form we are on dayOfMonth?: number; // day of birthday month?: number; // month of birthday } type MyContext = Context & SessionFlavor; const bot = new Bot(""); // Use session. bot.use(session({ initial: (): SessionData => ({ step: "idle" }) })); // Define some commands. bot.command("start", async (ctx) => { await ctx.reply(`Welcome! I can tell you in how many days it is your birthday! Send /birthday to start`); }); bot.command("birthday", async (ctx) => { const day = ctx.session.dayOfMonth; const month = ctx.session.month; if (day !== undefined && month !== undefined) { // Information already provided! await ctx.reply(`Your birthday is in ${getDays(month, day)} days!`); } else { // Missing information, enter router-based form ctx.session.step = "day"; await ctx.reply( "Please send me the day of month \n of your birthday as a number!" ); } }); // Use router. const router = new Router((ctx) => ctx.session.step); // Define step that handles the day. const day = router.route("day"); day.on("message:text", async (ctx) => { const day = parseInt(ctx.msg.text, 10); if (isNaN(day) || day < 1 || 31 < day) { await ctx.reply("That is not a valid day, try again!"); return; } ctx.session.dayOfMonth = day; // Advance form to step for month ctx.session.step = "month"; await ctx.reply("Got it! Now, send me the month!", { reply_markup: { one_time_keyboard: true, keyboard: new Keyboard() .text("Jan").text("Feb").text("Mar").row() .text("Apr").text("May").text("Jun").row() .text("Jul").text("Aug").text("Sep").row() .text("Oct").text("Nov").text("Dec").build(), }, }); }); day.use((ctx) => ctx.reply("Please send me the day as a text message!")); // Define step that handles the month. const month = router.route("month"); month.on("message:text", async (ctx) => { ``` -------------------------------- ### Choose deployment option Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/cloudflare-workers-nodejs.md Select whether to deploy your worker immediately after setup. It is recommended to choose 'No' to deploy after testing. ```ansi using create-cloudflare version 2.17.1 ╭ Create an application with Cloudflare Step 1 of 3 │ ├ In which directory do you want to create your application? │ dir ./grammybot │ ├ What type of application do you want to create? │ type "Hello World" Worker │ ├ Do you want to use TypeScript? │ yes typescript │ ├ Copying template files │ files copied to project directory │ ├ Updating name in `package.json` │ updated `package.json` │ ├ Installing dependencies │ installed via `npm install` │ ╰ Application created ╭ Configuring your application for Cloudflare Step 2 of 3 │ ├ Installing @cloudflare/workers-types │ installed via npm │ ├ Adding latest types to `tsconfig.json` │ added @cloudflare/workers-types/2023-07-01 │ ├ Retrieving current workerd compatibility date │ compatibility date 2024-04-05 │ ├ Do you want to use git for version control? │ yes git │ ├ Initializing git repo │ initialized git │ ├ Committing new files │ git commit │ ╰ Application configured ╭ Deploy with Cloudflare Step 3 of 3 │ ╰ Do you want to deploy your application? // [!code focus]   Yes / No // [!code focus] ``` -------------------------------- ### Example Project Structure for Translations Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/i18n.md Demonstrates a typical project directory structure for managing translation files using the Fluent format. It shows the placement of translation files within a 'locales/' directory. ```asciiart . ├── bot.ts └── locales/ ├── de.ftl ├── en.ftl ├── it.ftl └── ru.ftl ``` -------------------------------- ### TypeScript Quickstart Source: https://github.com/grammyjs/website/blob/main/site/docs/README.md Set up a basic Telegram bot using grammY in TypeScript. This snippet shows how to initialize the bot and reply to messages. ```typescript import { Bot } from "grammy"; const bot = new Bot(""); // <-- put your bot token between the "" (https://t.me/BotFather) // Reply to any message with "Hi there!". bot.on("message", (ctx) => ctx.reply("Hi there!")); bot.start(); ``` -------------------------------- ### JavaScript Quickstart Source: https://github.com/grammyjs/website/blob/main/site/docs/README.md Set up a basic Telegram bot using grammY in JavaScript. This snippet demonstrates bot initialization and message response. ```javascript const { Bot } = require("grammy"); const bot = new Bot(""); // <-- put your bot token between the "" (https://t.me/BotFather) // Reply to any message with "Hi there!". bot.on("message", (ctx) => ctx.reply("Hi there!")); bot.start(); ``` -------------------------------- ### Initialize Bot with Session and Router Source: https://github.com/grammyjs/website/blob/main/site/docs/zh/plugins/router.md Sets up the bot with session management and registers the router. The session is initialized with a 'step' property to track the conversation state. ```typescript import { Bot, Context, Keyboard, session, SessionFlavor, } from "https://deno.land/x/grammy/mod.ts"; import { Router } from "https://deno.land/x/grammy_router/router.ts"; interface SessionData { step: "idle" | "day" | "month"; // 我们在表单的哪一步 dayOfMonth?: number; // 生日日期 month?: number; // 生日月份 } type MyContext = Context & SessionFlavor; const bot = new Bot(""); // 使用会话。 bot.use(session({ initial: (): SessionData => ({ step: "idle" }) })); // 定义一些命令。 bot.command("start", async (ctx) => { await ctx.reply(`欢迎! 我可以告诉你还有几天到你的生日! 发送 /birthday 开始吧~`); }); bot.command("birthday", async (ctx) => { const day = ctx.session.dayOfMonth; const month = ctx.session.month; if (day !== undefined && month !== undefined) { // 已经提供了信息! await ctx.reply(`距离你的生日还有 ${getDays(month, day)} 天!`); } else { // 缺少信息,进入路由器的表单。 ctx.session.step = "day"; await ctx.reply("请把你生日的日期以数字形式发送给我~"); } }); // 使用路由器。 const router = new Router((ctx) => ctx.session.step); // 定义一个处理日期的步骤。 const day = router.route("day"); day.on("message:text", async (ctx) => { const day = parseInt(ctx.msg.text, 10); if (isNaN(day) || day < 1 || 31 < day) { await ctx.reply("啊哦,日期好像无效捏,再试一次吧!"); return; } ctx.session.dayOfMonth = day; // 提前进入月份的步骤 ctx.session.step = "month"; await ctx.reply("好嘞~现在请发送你的生日月份给我!", { reply_markup: { one_time_keyboard: true, keyboard: new Keyboard() .text("Jan").text("Feb").text("Mar").row() .text("Apr").text("May").text("Jun").row() .text("Jul").text("Aug").text("Sep").row() .text("Oct").text("Nov").text("Dec").build(), }, }); }); day.use((ctx) => ctx.reply("请把日期以文字消息形式发送给我!")); // 定义一个处理月份的步骤。 const month = router.route("month"); month.on("message:text", async (ctx) => { // 应该不会发生,除非会话数据被破坏。 const day = ctx.session.dayOfMonth; if (day === undefined) { await ctx.reply("咱还不知道你的生日日期和月份呢~"); ctx.session.step = "day"; return; } const month = months.indexOf(ctx.msg.text); if (month === -1) { await ctx.reply("啊哦,月份好像无效捏,请使用按钮发送~"); return; } ctx.session.month = month; const diff = getDays(month, day); await ctx.reply( `你的生日在 ${months[month]} ${day}。 还有 ${diff} 天就到啦!`, { reply_markup: { remove_keyboard: true } }, ); ctx.session.step = "idle"; }); month.use((ctx) => ctx.reply("请点击其中一个按钮!")); router.otherwise(async (ctx) => { await ctx.reply("发送 /birthday 看看还有多久到你的生日。"); }); bot.use(router); // 注册路由器 bot.start(); // 日期转换工具 const months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ]; function getDays(month: number, day: number) { const bday = new Date(); const now = Date.now(); bday.setMonth(month); bday.setDate(day); if (bday.getTime() < now) bday.setFullYear(bday.getFullYear() + 1); const diff = (bday.getTime() - now) / (1000 * 60 * 60 * 24); return diff; } ``` -------------------------------- ### Construct InputFile from Local Path or Stream Source: https://github.com/grammyjs/website/blob/main/site/docs/guide/files.md Provides examples of creating `InputFile` instances for uploading files from disk or from a read stream in Node.js, and from a local path or `Deno.FsFile` in Deno. ```typescript import { createReadStream } from "fs"; // Send a local file. new InputFile("/path/to/file"); // Send from a read stream. new InputFile(createReadStream("/path/to/file")); ``` ```typescript // Send a local file. new InputFile("/path/to/file"); // Send a `Deno.FsFile` instance. new InputFile(await Deno.open("/path/to/file")); ``` -------------------------------- ### Prepare Bot Code for Deno Deploy Webhooks Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/deno-deploy.md This snippet demonstrates how to set up a bot for Deno Deploy using webhooks. It imports the `webhookCallback` function and your bot object, then creates an HTTP server to handle incoming updates. Ensure your bot object is correctly imported and that you are using `webhookCallback` instead of `bot.start()`. ```typescript import { webhookCallback } from "https://deno.land/x/grammy/mod.ts"; // You might modify this to the correct way to import your `Bot` object. import bot from "./bot.ts"; const handleUpdate = webhookCallback(bot, "std/http"); Deno.serve(async (req) => { if (req.method === "POST") { const url = new URL(req.url); if (url.pathname.slice(1) === bot.token) { try { return await handleUpdate(req); } catch (err) { console.error(err); } } } return new Response(); }); ``` -------------------------------- ### JavaScript Session Example Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/session.md Example bot that counts pizza emojis using session data in JavaScript. Requires session middleware. ```javascript const { Bot, session } = require("grammy"); const bot = new Bot(""); // Install session middleware, and define the initial session value. function initial() { return { pizzaCount: 0 }; } bot.use(session({ initial })); bot.command("hunger", async (ctx) => { const count = ctx.session.pizzaCount; await ctx.reply(`Your hunger level is ${count}!`); }); bot.hears(/.*🍕.*/, (ctx) => ctx.session.pizzaCount++); bot.start(); ``` -------------------------------- ### Select the worker type Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/cloudflare-workers-nodejs.md Choose the type of worker you want to create. For a basic setup, select "Hello World" Worker. ```ansi using create-cloudflare version 2.17.1 ╭ Create an application with Cloudflare Step 1 of 3 │ ├ In which directory do you want to create your application? │ dir ./grammybot │ ╰ What type of application do you want to create? // [!code focus]   ● "Hello World" Worker // [!code focus]   ○ "Hello World" Worker (Python) // [!code focus]   ○ "Hello World" Durable Object // [!code focus]   ○ Website or web app // [!code focus]   ○ Example router & proxy Worker // [!code focus]   ○ Scheduled Worker (Cron Trigger) // [!code focus]   ○ Queue consumer & producer Worker // [!code focus]   ○ API starter (OpenAPI compliant) // [!code focus]   ○ Worker built from a template hosted in a git repository // [!code focus] ``` -------------------------------- ### Long Polling Bot Start (Node.js) Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/fly.md Starts a grammY bot using long polling in Node.js. It retrieves the bot token from environment variables and sets up a basic 'start' command handler. It also configures process listeners for graceful shutdown. ```ts import { Bot } from "grammy"; const token = process.env.BOT_TOKEN; if (!token) throw new Error("BOT_TOKEN is unset"); const bot = new Bot(token); bot.command( "start", (ctx) => ctx.reply("I'm running on Fly using long polling!"), ); process.once("SIGINT", () => bot.stop()); process.once("SIGTERM", () => bot.stop()); bot.start(); ``` -------------------------------- ### Long Polling Bot Start (Deno) Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/fly.md Starts a grammY bot using long polling in Deno. It retrieves the bot token from environment variables and sets up a basic 'start' command handler. It also configures signal listeners for graceful shutdown. ```ts import { Bot } from "https://deno.land/x/grammy/mod.ts"; const token = Deno.env.get("BOT_TOKEN"); if (!token) throw new Error("BOT_TOKEN is unset"); const bot = new Bot(token); bot.command( "start", (ctx) => ctx.reply("I'm running on Fly using long polling!"), ); Deno.addSignalListener("SIGINT", () => bot.stop()); Deno.addSignalListener("SIGTERM", () => bot.stop()); bot.start(); ``` -------------------------------- ### TypeScript Session Example Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/session.md Example bot that counts pizza emojis using session data. Requires session middleware and context flavor. ```typescript import { Bot, Context, session, SessionFlavor, } from "grammy"; // Define the shape of our session. interface SessionData { pizzaCount: number; } // Flavor the context type to include sessions. type MyContext = Context & SessionFlavor; const bot = new Bot(""); // Install session middleware, and define the initial session value. function initial(): SessionData { return { pizzaCount: 0 }; } bot.use(session({ initial })); bot.command("hunger", async (ctx) => { const count = ctx.session.pizzaCount; await ctx.reply(`Your hunger level is ${count}!`); }); bot.hears(/.*🍕.*/, (ctx) => ctx.session.pizzaCount++); bot.start(); ``` -------------------------------- ### Setup I18n Plugin Without Sessions (TypeScript, JavaScript, Deno) Source: https://github.com/grammyjs/website/blob/main/site/docs/plugins/i18n.md Demonstrates how to initialize and use the Grammy.js I18n plugin for multi-language support without session management. It configures the default locale and translation directory, then registers the plugin with the bot. Translations are accessed using `ctx.t`. ```TypeScript import { Bot, Context } from "grammy"; import { I18n, I18nFlavor } from "@grammyjs/i18n"; type MyContext = Context & I18nFlavor; const bot = new Bot(""); const i18n = new I18n({ defaultLocale: "en", directory: "locales", }); bot.use(i18n); bot.command("start", async (ctx) => { await ctx.reply(ctx.t("start-msg")); }); ``` ```JavaScript const { Bot } = require("grammy"); const { I18n } = require("@grammyjs/i18n"); const bot = new Bot(""); const i18n = new I18n({ defaultLocale: "en", directory: "locales", }); bot.use(i18n); bot.command("start", async (ctx) => { await ctx.reply(ctx.t("start-msg")); }); ``` ```Deno import { Bot, Context } from "https://deno.land/x/grammy/mod.ts"; import { I18n, I18nFlavor } from "https://deno.land/x/grammy_i18n/mod.ts"; type MyContext = Context & I18nFlavor; const bot = new Bot(""); const i18n = new I18n({ defaultLocale: "en", directory: "locales", }); // await i18n.loadLocalesDir("locales"); bot.use(i18n); bot.command("start", async (ctx) => { await ctx.reply(ctx.t("start-msg")); }); ``` -------------------------------- ### Start Deno bot locally Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/zeabur-deno.md Command to run the bot locally, which triggers dependency resolution and lock file generation. ```sh deno -IN main.ts ``` -------------------------------- ### Install Emoji Plugin (JavaScript) Source: https://github.com/grammyjs/website/blob/main/site/docs/zh/plugins/emoji.md Install the emoji plugin in your JavaScript project. This involves importing the necessary components and using the emojiParser middleware. ```javascript const { Bot } = require("grammy"); const { emojiParser } = require("@grammyjs/emoji"); const bot = new Bot(""); bot.use(emojiParser()); ``` -------------------------------- ### Install grammY Dependency Source: https://github.com/grammyjs/website/blob/main/site/docs/hosting/cloudflare-workers-nodejs.md Install the grammY library and any other necessary packages for your bot. This command should be run inside your worker's project directory. ```sh npm install grammy ```