diff --git a/site/docs/.vitepress/configs/locales/en.ts b/site/docs/.vitepress/configs/locales/en.ts index 742686ab3..06d930942 100644 --- a/site/docs/.vitepress/configs/locales/en.ts +++ b/site/docs/.vitepress/configs/locales/en.ts @@ -340,6 +340,10 @@ const hostingTutorials = { text: "Vercel", link: "/hosting/vercel", }, + { + text: "Cyclic", + link: "/hosting/cyclic", + }, { text: "Virtual Private Server", link: "/hosting/vps", diff --git a/site/docs/.vitepress/configs/locales/es.ts b/site/docs/.vitepress/configs/locales/es.ts index b42f3bb89..0f6a72633 100644 --- a/site/docs/.vitepress/configs/locales/es.ts +++ b/site/docs/.vitepress/configs/locales/es.ts @@ -336,6 +336,10 @@ const hostingTutorials = { text: "Vercel", link: "/es/hosting/vercel", }, + { + text: "Cyclic", + link: "/hosting/cyclic", + }, { text: "Servidor Privado Virtual", link: "/es/hosting/vps", diff --git a/site/docs/.vitepress/configs/locales/id.ts b/site/docs/.vitepress/configs/locales/id.ts index 9b20af648..6ae32ff88 100644 --- a/site/docs/.vitepress/configs/locales/id.ts +++ b/site/docs/.vitepress/configs/locales/id.ts @@ -332,6 +332,10 @@ const hostingTutorials = { text: "Vercel", link: "/id/hosting/vercel", }, + { + text: "Cyclic", + link: "/id/hosting/cyclic", + }, { text: "Virtual Private Server", link: "/id/hosting/vps", diff --git a/site/docs/.vitepress/configs/locales/uk.ts b/site/docs/.vitepress/configs/locales/uk.ts index bbf8c2ad9..93ade7fe7 100644 --- a/site/docs/.vitepress/configs/locales/uk.ts +++ b/site/docs/.vitepress/configs/locales/uk.ts @@ -340,6 +340,10 @@ const hostingTutorials = { text: "Vercel", link: "/uk/hosting/vercel", }, + { + text: "Cyclic", + link: "/uk/hosting/cyclic", + }, { text: "Віртуальний приватний сервер", link: "/uk/hosting/vps", diff --git a/site/docs/.vitepress/configs/locales/zh.ts b/site/docs/.vitepress/configs/locales/zh.ts index 6f2e0dc70..6aff55f4e 100644 --- a/site/docs/.vitepress/configs/locales/zh.ts +++ b/site/docs/.vitepress/configs/locales/zh.ts @@ -340,6 +340,10 @@ const hostingTutorials = { text: "Vercel", link: "/zh/hosting/vercel", }, + { + text: "Cyclic", + link: "/zh/hosting/cyclic", + }, { text: "Virtual Private Server", link: "/zh/hosting/vps", diff --git a/site/docs/es/hosting/comparison.md b/site/docs/es/hosting/comparison.md index 216db9984..01c7ff7e6 100644 --- a/site/docs/es/hosting/comparison.md +++ b/site/docs/es/hosting/comparison.md @@ -46,6 +46,7 @@ En su lugar, a menudo tendrás que tener una base de datos por separado y conect | DigitalOcean Functions | Gratis | $1.85/100K GB-s | [90K GB-s/mes](https://docs.digitalocean.com/products/functions/details/pricing/) | ✅ | ❌ | ❓ | | | Cloudflare Workers | Gratis | $5/10M solicitudes | [100K solicitudes/día, Límite de tiempo de CPU de 10 ms](https://workers.cloudflare.com/) | ❌ | [✅](https://denoflare.dev/) | ✅ | | | Vercel | Gratis | $20/mes suscripción | [Invocaciones ilimitadas, 100 GB-h, Límite de tiempo de 10 s](https://vercel.com/pricing) | [✅](https://vercel.com/docs/concepts/functions/serverless-functions/runtimes/node-js) | [✅](https://github.com/vercel-community/deno) | [✅](https://vercel.com/docs/frameworks) | | +| Cyclic.sh | Free | $1/mes por app, $0.50 por 100K | [10K solicitudes/mes](https://docs.cyclic.sh/overview/limits) | ✅ | ❓ | ❓ | | | Scaleway Functions | Gratis | €0.15/1M solicitudes, €1.2/100K GB-s | [1M de solicitudes, 400K GB-s/mes](https://www.scaleway.com/en/pricing/?tags=serverless-functions-serverlessfunctions) | ❓ | ❓ | ❓ | | | Scaleway Containers | Gratis | €0.10/100K GB-s, €1.0/100K vCPU-s | [400K GB-s, 200K vCPU-s/mes](https://www.scaleway.com/en/pricing/?tags=serverless-containers-serverlesscontainers) | ❓ | ❓ | ❓ | | | Vercel Edge Functions | Gratis | $20/mes suscripción por 500K | [100K solicitudes/día](https://vercel.com/pricing) | [✅](https://vercel.com/docs/concepts/functions/edge-functions/edge-runtime#compatible-node.js-modules) | ❓ | [✅](https://vercel.com/templates/edge-functions) | | diff --git a/site/docs/es/hosting/cyclic.md b/site/docs/es/hosting/cyclic.md new file mode 100644 index 000000000..e2d73eb5e --- /dev/null +++ b/site/docs/es/hosting/cyclic.md @@ -0,0 +1,159 @@ +--- +prev: false +next: false +--- + +# Alojamiento: Cyclic + +Esta guía te explica cómo puedes alojar tus bots grammY en [Cyclic](https://cyclic.sh). + +## Requisitos previos + +Para seguir adelante, necesitas tener una cuenta [Github](https://github.com) y [Cyclic](https://cyclic.sh). +Primero, inicializa tu proyecto e instala algunas dependencias: + +```sh +# Inicializa el proyecto. +mkdir grammy-bot +cd grammy-bot +npm init -y + +# Instalar dependencias principales. +npm install grammy express dotenv + +# Instalar dependencias de desarrollo. +npm install -D typescript ts-node nodemon @types/express @types/node + +# Inicializar la configuración de TypeScript. +npx tsc --init +``` + +Almacenaremos nuestros archivos TypeScript dentro de `src/`, y nuestros archivos compilados en `dist/`. +Después de crear ambos, entra en `src/`, y crea un archivo llamado `bot.ts`. +El directorio raíz de tu proyecto debería tener ahora este aspecto: + +```asciiart:no-line-numbers +. +├── node_modules/ +├── dist/ +├── src/ +│ └── bot.ts +├── package.json +├── package-lock.json +└── tsconfig.json +``` + +A continuación, abra `tsconfig.json`, y reescriba su contenido para utilizar esta configuración: + +```json +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "esModuleInterop": true, + "skipLibCheck": true, + "strict": true + } +} +``` + +Y luego tenemos que añadir los scripts `start`, `build` y `dev` a nuestro `package.json`. +Nuestro `package.json` ahora debe ser similar a esto: + +```json{6-10} +{ + "name": "grammy-bot", + "version": "1.0.0", + "description": "", + "main": "dist/bot.js", + "scripts": { + "build": "tsc", + "start": "node dist/bot.js", + "dev": "nodemon src/bot.ts" + }, + "license": "ISC", + "dependencies": { + "express": "^4.18.2", + "grammy": "^1.17.2", + "dotenv": "^16.3.1" + }, + "devDependencies": { + "@types/express": "^4.17.17", + "@types/node": "^20.4.9", + "typescript": "^5.1.6", + "nodemon": "^3.0.1", + "ts-node": "^10.9.1" + }, + "keywords": [] +} +``` + +### Webhooks + +Abre `src/bot.ts` y escribe el siguiente contenido en él: + +```ts{15} +import express from "express"; +import { Bot, webhookCallback } from "grammy"; +import "dotenv/config"; + +const bot = new Bot(process.env.BOT_TOKEN || ""); + +bot.command("start", (ctx) => ctx.reply("¡Hola Mundo!")) + +if (process.env.NODE_ENV === "DEVELOPMENT") { + bot.start(); +} else { + const port = process.env.PORT || 3000; + const app = express(); + app.use(express.json()); + app.use(`/${bot.token}`, webhookCallback(bot, "express")); + app.listen(port, () => console.log(`escuchando en el puerto ${port}`)); +} +``` + +Te recomendamos que tengas tu controlador de webhooks en una ruta secreta en lugar de `/`. +Como se muestra en la línea resaltada arriba, estamos usando `/` en lugar de `/`. + +### Desarrollo Local + +Cree un archivo `.env` en la raíz de su proyecto con el siguiente contenido: + +``` +BOT_TOKEN= +NODE_ENV=DEVELOPMENT +``` + +Después, ejecuta tu script `dev`: + +```sh +npm run dev +``` + +Nodemon vigilará tu archivo `bot.ts` y reiniciará tu bot en cada cambio de código. + +## Despliegue + +1. Crea un repositorio en GitHub, puede ser privado o público. +2. Empuja tu código. + +> Es recomendable que tengas una única rama estable y hagas tus pruebas en ramas separadas, para no desplegar comportamientos inesperados en producción. + +3. Visita tu [Cyclic dashboard](https://app.cyclic.sh). +4. Haz clic en "Link Your Own" y selecciona tu repositorio. +5. Vaya a Avanzado > Variables y añada su `BOT_TOKEN`. +6. Despliega tu bot con "Connect Cyclic". + +### Configuración de la URL del webhook + +Si estás usando webhooks, después de tu primer despliegue, deberías configurar los ajustes de webhook de tu bot para que apunten a tu app. +Para ello, envía una petición a + +```text +https://api.telegram.org/bot/setWebhook?url=/ +``` + +sustituyendo `` por tu token de bot, y `` por la URL completa de tu aplicación junto con la ruta al controlador del webhook. + +Enhorabuena. +Tu bot ya debería estar funcionando. diff --git a/site/docs/es/plugins/conversations.md b/site/docs/es/plugins/conversations.md index a8c1dca17..f87c384c4 100644 --- a/site/docs/es/plugins/conversations.md +++ b/site/docs/es/plugins/conversations.md @@ -464,7 +464,7 @@ bot.command("cancel", async (ctx) => { await ctx.reply("Saliendo."); }); -// Salir siempre de la conversación de la `movie` +// Salir siempre de la conversación de la `movie` // cuando se pulsa el botón de `cancel` del teclado en línea. bot.callbackQuery("cancel", async (ctx) => { await ctx.conversation.exit("movie"); @@ -489,7 +489,7 @@ bot.command("cancel", async (ctx) => { await ctx.reply("Saliendo."); }); -// Salir siempre de la conversación de la `movie` +// Salir siempre de la conversación de la `movie` // cuando se pulsa el botón de `cancel` del teclado en línea. bot.callbackQuery("cancel", async (ctx) => { await ctx.conversation.exit("movie"); diff --git a/site/docs/hosting/comparison.md b/site/docs/hosting/comparison.md index 96dfeda84..2695e7a82 100644 --- a/site/docs/hosting/comparison.md +++ b/site/docs/hosting/comparison.md @@ -49,6 +49,7 @@ Instead, you will often have to have a database separately and connect to it if | Scaleway Functions | Free | €0.15/1M req, €1.2/100K GB-s | [1M requests, 400K GB-s/mo](https://www.scaleway.com/en/pricing/?tags=serverless-functions-serverlessfunctions) | ❓ | ❓ | ❓ | | | Scaleway Containers | Free | €0.10/100K GB-s, €1.0/100K vCPU-s | [400K GB-s, 200K vCPU-s/mo](https://www.scaleway.com/en/pricing/?tags=serverless-containers-serverlesscontainers) | ❓ | ❓ | ❓ | | | Vercel Edge Functions | Free | $20/mo subscription for 500K | [100K req/day](https://vercel.com/pricing) | [✅](https://vercel.com/docs/concepts/functions/edge-functions/edge-runtime#compatible-node.js-modules) | ❓ | [✅](https://vercel.com/templates/edge-functions) | | +| Cyclic.sh | Free | $1/mo per app, $0.50 for 100K | [10K req/mo](https://docs.cyclic.sh/overview/limits) | ✅ | ❓ | ❓ | | | serverless.com | Free | | | ❓ | ❓ | ❓ | | | Heroku | $5 | $5 for 1,000 [dyno hours](https://devcenter.heroku.com/articles/usage-and-billing#dyno-usage-and-costs)/mo | [512MB RAM, sleeps after 30 mins of inactivity](https://www.heroku.com/pricing) | ✅ | ✅ | ❓ | Deno is supported by a [third-party buildpack](https://github.com/chibat/heroku-buildpack-deno). | | DigitalOcean Apps | $5 | | | ❓ | ❓ | ❓ | Not tested | diff --git a/site/docs/hosting/cyclic.md b/site/docs/hosting/cyclic.md new file mode 100644 index 000000000..e35969566 --- /dev/null +++ b/site/docs/hosting/cyclic.md @@ -0,0 +1,159 @@ +--- +prev: false +next: false +--- + +# Hosting: Cyclic + +This guide tells you how you can host your grammY bots on [Cyclic](https://cyclic.sh). + +## Prerequisites + +To follow along, you need to have a [Github](https://github.com) and [Cyclic](https://cyclic.sh) account. +First, initialize your project and install some dependencies: + +```sh +# Initialize the project. +mkdir grammy-bot +cd grammy-bot +npm init -y + +# Install main dependencies. +npm install grammy express dotenv + +# Install development dependencies. +npm install -D typescript ts-node nodemon @types/express @types/node + +# Initialize TypeScript config. +npx tsc --init +``` + +We will store our TypeScript files inside `src/`, and our compiled files in `dist/`. +After creating both of them, cd into `src/`, and create a file named `bot.ts`. +Your project's root directory should now look like this: + +```asciiart:no-line-numbers +. +├── node_modules/ +├── dist/ +├── src/ +│ └── bot.ts +├── package.json +├── package-lock.json +└── tsconfig.json +``` + +Then, open `tsconfig.json`, and rewrite its contents to use this configuration: + +```json +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "esModuleInterop": true, + "skipLibCheck": true, + "strict": true + } +} +``` + +And then we have to add `start`, `build` and `dev` scripts to our `package.json`. +Our `package.json` should now be similar to this: + +```json{6-10} +{ + "name": "grammy-bot", + "version": "1.0.0", + "description": "", + "main": "dist/bot.js", + "scripts": { + "build": "tsc", + "start": "node dist/bot.js", + "dev": "nodemon src/bot.ts" + }, + "license": "ISC", + "dependencies": { + "express": "^4.18.2", + "grammy": "^1.17.2", + "dotenv": "^16.3.1" + }, + "devDependencies": { + "@types/express": "^4.17.17", + "@types/node": "^20.4.9", + "typescript": "^5.1.6", + "nodemon": "^3.0.1", + "ts-node": "^10.9.1" + }, + "keywords": [] +} +``` + +### Webhooks + +Open `src/bot.ts` write the following contents to it: + +```ts{15} +import express from "express"; +import { Bot, webhookCallback } from "grammy"; +import "dotenv/config"; + +const bot = new Bot(process.env.BOT_TOKEN || ""); + +bot.command("start", (ctx) => ctx.reply("Hello World!")) + +if (process.env.NODE_ENV === "DEVELOPMENT") { + bot.start(); +} else { + const port = process.env.PORT || 3000; + const app = express(); + app.use(express.json()); + app.use(`/${bot.token}`, webhookCallback(bot, "express")); + app.listen(port, () => console.log(`listening on port ${port}`)); +} +``` + +We recommend that you have your webhook handler on a secret path rather than `/`. +As shown in the highlighted line above, we are using the `/` instead of `/`. + +### Local Development + +Create a `.env` file at the root of your project with the following contents: + +``` +BOT_TOKEN= +NODE_ENV=DEVELOPMENT +``` + +After that, run your `dev` script: + +```sh +npm run dev +``` + +Nodemon will watch your `bot.ts` file and restart your bot on every code change. + +## Deploying + +1. Create a repository on GitHub, it can be either private or public. +2. Push your code. + +> It is recommended that you have a single stable branch and you do your testing in separate branches, so that you won't land unexpected behaviors to production. + +3. Visit your [Cyclic dashboard](https://app.cyclic.sh). +4. Click "Link Your Own" and select your repository. +5. Go to Advanced > Variables and add your `BOT_TOKEN`. +6. Deploy your bot with "Connect Cyclic". + +### Setting the Webhook URL + +If you are using webhooks, after your first deployment, you should configure your bot's webhook settings to point to your app. +To do that, send a request to + +```text +https://api.telegram.org/bot/setWebhook?url=/ +``` + +replacing `` with your bot token, and `` with the full URL of your app along with the path to the webhook handler. + +Congratulations! +Your bot should now be up and running. diff --git a/site/docs/id/hosting/cyclic.md b/site/docs/id/hosting/cyclic.md new file mode 100644 index 000000000..1e3a9d8e6 --- /dev/null +++ b/site/docs/id/hosting/cyclic.md @@ -0,0 +1,159 @@ +--- +prev: false +next: false +--- + +# Hosting: Cyclic + +Panduan ini berisi langkah-langkah untuk menjalankan bot grammY di [Cyclic](https://cyclic.sh). + +## Prasyarat + +Sebelum memulai, kamu diharuskan memiliki sebuah akun [GitHub](https://github.com) dan [Cyclic](https://cyclic.sh). +Pertama-tama, inisialisasi proyeknya lalu instal beberapa dependensi berikut: + +```sh +# Inisialisasi proyek. +mkdir grammy-bot +cd grammy-bot +npm init -y + +# Instal dependensi utama. +npm install grammy express dotenv + +# Instal dependensi pengembangan. +npm install -D typescript ts-node nodemon @types/express @types/node + +# Inisialisasi pengaturan TypeScript. +npx tsc --init +``` + +Kita akan menyimpan file TypeScript di dalam `src/` dan file hasil kompilasinya di `dist/`. +Setelah membuat kedua folder, cd ke `src/` lalu buat sebuah file bernama `bot.ts`. +Sekarang, struktur direktori root kita seharusnya mirip seperti ini: + +```asciiart:no-line-numbers +. +├── node_modules/ +├── dist/ +├── src/ +│ └── bot.ts +├── package.json +├── package-lock.json +└── tsconfig.json +``` + +Selanjutnya, buka `tsconfig.json` lalu ganti isinya dengan konfigurasi berikut: + +```json +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "esModuleInterop": true, + "skipLibCheck": true, + "strict": true + } +} +``` + +Kemudian, kita akan menambahkan script `start`, `build`, serta `dev` ke `package.json`. +Isi `package.json` kita kurang lebih menjadi seperti ini: + +```json{6-10} +{ + "name": "grammy-bot", + "version": "1.0.0", + "description": "", + "main": "dist/bot.js", + "scripts": { + "build": "tsc", + "start": "node dist/bot.js", + "dev": "nodemon src/bot.ts" + }, + "license": "ISC", + "dependencies": { + "express": "^4.18.2", + "grammy": "^1.17.2", + "dotenv": "^16.3.1" + }, + "devDependencies": { + "@types/express": "^4.17.17", + "@types/node": "^20.4.9", + "typescript": "^5.1.6", + "nodemon": "^3.0.1", + "ts-node": "^10.9.1" + }, + "keywords": [] +} +``` + +### Webhooks + +Buka `src/bot.ts` lalu isi dengan kode berikut: + +```ts{15} +import express from "express"; +import { Bot, webhookCallback } from "grammy"; +import "dotenv/config"; + +const bot = new Bot(process.env.BOT_TOKEN || ""); + +bot.command("start", (ctx) => ctx.reply("Halo Dunia!")) + +if (process.env.NODE_ENV === "DEVELOPMENT") { + bot.start(); +} else { + const port = process.env.PORT || 3000; + const app = express(); + app.use(express.json()); + app.use(`/${bot.token}`, webhookCallback(bot, "express")); + app.listen(port, () => console.log(`Menyimak di port ${port}`)); +} +``` + +Untuk alasan keamanan, penanganan webhook sebaiknya diletakkan di path tersembunyi alih-alih di `/`. +Seperti yang terlihat pada baris yang disorot di atas, kita menggunakan path `/` alih-alih di `/`. + +### Pengembangan Lokal + +Buat sebuah file `.env` di root proyek lalu isi dengan konten berikut: + +``` +BOT_TOKEN= +NODE_ENV=DEVELOPMENT +``` + +Setelah itu, jalankan script `dev`-nya: + +```sh +npm run dev +``` + +Nodemon akan memantau file `bot.ts` dan memulai ulang bot ketika terjadi perubahan kode. + +## Men-deploy + +1. Buat sebuah repositori di GitHub, bisa berupa privat ataupun publik. +2. Push kodenya. + +> Disarankan memiliki branch utama untuk produksi dan branch terpisah untuk melakukan pengetesan agar tidak terjadi hal-hal yang tidak diinginkan di tahap produksi. + +3. Kunjungi [dashboard Cyclic](https://app.cyclic.sh). +4. Klik "Link Your Own" lalu pilih repositorinya. +5. Pergi ke Advanced > Variables, kemudian tambahkan `BOT_TOKEN`-nya. +6. Deploy bot dengan "Connect Cyclic". + +### Mengatur URL Webhook + +Jika kamu menggunakan webhooks, tepat setelah melakukan deployment, kamu perlu mengarahkan webhook bot ke app yang barusan kamu deploy. +Untuk melakukannya, kirim request ke + +```text +https://api.telegram.org/bot/setWebhook?url=/ +``` + +Ganti `` dengan token bot serta `` dengan URL app kamu lengkap beserta path penanganan webhook-nya. + +Selamat! +Bot kamu sekarang siap untuk digunakan. diff --git a/site/docs/id/plugins/conversations.md b/site/docs/id/plugins/conversations.md index 8da4eef4d..b039528bd 100644 --- a/site/docs/id/plugins/conversations.md +++ b/site/docs/id/plugins/conversations.md @@ -492,7 +492,7 @@ bot.command("cancel", async (ctx) => { await ctx.reply("Keluar."); }); -// Keluar dari percakapan `movie` ketika tombol `cancel` +// Keluar dari percakapan `movie` ketika tombol `cancel` // di inline keyboard ditekan bot.callbackQuery("cancel", async (ctx) => { await ctx.conversation.exit("movie"); @@ -1055,7 +1055,7 @@ Sebagai contoh, mari kita implementasikan kembali contoh captcha di atas, tetapi async function captcha(conversation: MyConversation, ctx: MyContext) { if (ctx.from === undefined) return false; await ctx.reply( - "Buktikan kalau kamu manusia! \ +"Buktikan kalau kamu manusia! \ Apa jawaban untuk kehidupan, alam semesta, dan semuanya?", ); const { message } = await conversation.waitFrom(ctx.from); @@ -1074,7 +1074,7 @@ async function enterGroup(conversation: MyConversation, ctx: MyContext) { async function captcha(conversation, ctx) { if (ctx.from === undefined) return false; await ctx.reply( - "Buktikan kalau kamu manusia! \ +"Buktikan kalau kamu manusia! \ Apa jawaban untuk kehidupan, alam semesta, dan semuanya?", ); const { message } = await conversation.waitFrom(ctx.from); diff --git a/site/docs/uk/hosting/comparison.md b/site/docs/uk/hosting/comparison.md index 8380d355c..ceda0b2d1 100644 --- a/site/docs/uk/hosting/comparison.md +++ b/site/docs/uk/hosting/comparison.md @@ -41,7 +41,7 @@ next: false | Назва | Мін. ціна | Тарифи | Ліміти | Node.js | Deno | Веб | Замітки | | ---------------------- | ----------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Deta | Безкоштовно | Немає платних тарифів | Не вказані ліміти | ✅ | ✅ | ✅ | Deno підтримується як [користувацький застосунок](https://deta.space/docs/en/build/quick-starts/custom) ([приклад](https://github.com/deta/starters/tree/main/deno-app)). | -| Deno Deploy | Безкоштовно | 20 $/міс. підписка для 5M зап. та 100 ГБ; 2 $/1M зап., 0.5 $/ГБ мережа | [1М зап./міс, 100 ГБ/міс., 10 мс CPU час обмеження](https://deno.com/deploy/pricing) | ❌ | ✅ | ❌ | | +| Deno Deploy | Безкоштовно | 20 $/міс. підписка для 5M зап. та 100 ГБ; 2 $/1M зап., 0.5 $/ГБ мережа | [1М зап./міс., 100 ГБ/міс., 10 мс CPU час обмеження](https://deno.com/deploy/pricing) | ❌ | ✅ | ❌ | | | Fly | Безкоштовно | 1.94 $/міс. подписка для shared-cpu-1x та 256 МБ RAM, 0.02 $/ГБ мережа | [3 shared-cpu-1x 256 МБ VMs, 160 ГБ/міс., 3 ГБ сховище](https://fly.io/docs/about/pricing/) | ✅ | ✅ | ❓ | | | DigitalOcean Functions | Безкоштовно | 1.85 $/100K ГБ-с | [90K ГБ-с/міс.](https://docs.digitalocean.com/products/functions/details/pricing/) | ✅ | ❌ | ❓ | | | Cloudflare Workers | Безкоштовно | 5 $/10M зап. | [100K зап./день, 10 мс CPU час обмеження](https://workers.cloudflare.com/) | ❌ | [✅](https://denoflare.dev/) | ✅ | | @@ -49,6 +49,7 @@ next: false | Scaleway Functions | Безкоштовно | 0.15 €/1M зап., 1.2 €/100K ГБ-с | [1M запитів, 400K ГБ-с/міс.](https://www.scaleway.com/en/pricing/?tags=serverless-functions-serverlessfunctions) | ❓ | ❓ | ❓ | | | Scaleway Containers | Безкоштовно | 0.10 €/100K ГБ-с, 1 €/100K vCPU-с | [400K ГБ-с, 200K vCPU-с/міс.](https://www.scaleway.com/en/pricing/?tags=serverless-containers-serverlesscontainers) | ❓ | ❓ | ❓ | | | Vercel Edge Functions | Безкоштовно | 20 $/міс. підписка для 500K | [100K зап./день](https://vercel.com/pricing) | [✅](https://vercel.com/docs/concepts/functions/edge-functions/edge-runtime#compatible-node.js-modules) | ❓ | ❓ | | +| Cyclic.sh | Безкоштовно | 1 $/міс. для кожного застосунку, 0.50 $ для 100K | [10K зап./міс.](https://docs.cyclic.sh/overview/limits) | ✅ | ❓ | ❓ | | | serverless.com | Безкоштовно | | | ❓ | ❓ | ❓ | | | Heroku | 5 $ | 5 $ за 1,000 [dyno годин](https://devcenter.heroku.com/articles/usage-and-billing#dyno-usage-and-costs)/міс. | [512 МБ RAM, сплячий режим після 30 хв бездіяльності](https://www.heroku.com/pricing) | ✅ | ✅ | ❓ | Deno підтримується як [сторонній buildpack](https://github.com/chibat/heroku-buildpack-deno). | | DigitalOcean Apps | 5 $ | | | ❓ | ❓ | ❓ | Не перевірено | diff --git a/site/docs/uk/hosting/cyclic.md b/site/docs/uk/hosting/cyclic.md new file mode 100644 index 000000000..8bcdc9db5 --- /dev/null +++ b/site/docs/uk/hosting/cyclic.md @@ -0,0 +1,159 @@ +--- +prev: false +next: false +--- + +# Хостинг: Cyclic + +У цьому посібнику ви дізнаєтеся, як розмістити ваших ботів на grammY на [Cyclic](https://cyclic.sh). + +## Передумови + +Щоб почати, вам потрібно мати обліковий запис [Github](https://github.com) та [Cyclic](https://cyclic.sh). +Спочатку ініціалізуйте ваш проєкт та встановіть деякі залежності: + +```sh +# Ініціалізуємо проєкт. +mkdir grammy-bot +cd grammy-bot +npm init -y + +# Встановлюємо основні залежності. +npm install grammy express dotenv + +# Встановлюємо залежності для розробки. +npm install -D typescript ts-node nodemon @types/express @types/node + +# Ініціалізуємо конфіг TypeScript. +npx tsc --init +``` + +Ми зберігатимемо наші файли TypeScript у каталозі `src/`, а скомпільовані файли --- у каталозі `dist/`. +Після створення обох каталогів перейдіть до каталогу `src/` і створіть файл з назвою `bot.ts`. +Тепер кореневий каталог вашого проекту має виглядати так: + +```asciiart:no-line-numbers +. +├── node_modules/ +├── dist/ +├── src/ +│ └── bot.ts +├── package.json +├── package-lock.json +└── tsconfig.json +``` + +Потім відкрийте `tsconfig.json` і перепишіть його вміст, щоб використовувати наступну конфігурацію: + +```json +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "esModuleInterop": true, + "skipLibCheck": true, + "strict": true + } +} +``` + +Після цього ви повинні додати до вашого `package.json` скрипти `start`, `build` і `dev`. +Тепер ваш `package.json` має виглядати приблизно так: + +```json{6-10} +{ + "name": "grammy-bot", + "version": "1.0.0", + "description": "", + "main": "dist/bot.js", + "scripts": { + "build": "tsc", + "start": "node dist/bot.js", + "dev": "nodemon src/bot.ts" + }, + "license": "ISC", + "dependencies": { + "express": "^4.18.2", + "grammy": "^1.17.2", + "dotenv": "^16.3.1" + }, + "devDependencies": { + "@types/express": "^4.17.17", + "@types/node": "^20.4.9", + "typescript": "^5.1.6", + "nodemon": "^3.0.1", + "ts-node": "^10.9.1" + }, + "keywords": [] +} +``` + +### Вебхуки + +Відкрийте файл `src/bot.ts` і запишіть до нього наступний вміст: + +```ts{15} +import express from "express"; +import { Bot, webhookCallback } from "grammy"; +import "dotenv/config"; + +const bot = new Bot(process.env.BOT_TOKEN || ""); + +bot.command("start", (ctx) => ctx.reply("Привіт, світ!")) + +if (process.env.NODE_ENV === "DEVELOPMENT") { + bot.start(); +} else { + const port = process.env.PORT || 3000; + const app = express(); + app.use(express.json()); + app.use(`/${bot.token}`, webhookCallback(bot, "express")); + app.listen(port, () => console.log(`Прослуховується порт ${port}`)); +} +``` + +Ми рекомендуємо розміщувати обробник вебхука на секретному шляху, а не на `/`. +Як показано у виділеному рядку вище, ми використовуємо `/<токен-бота>` замість простого `/`. + +### Локальна розробка + +Створіть файл `.env` у корені вашого проєкту з наступним вмістом: + +``` +BOT_TOKEN=<токен-бота> +NODE_ENV=DEVELOPMENT +``` + +Після цього запустіть ваш скрипт `dev`: + +```sh +npm run dev +``` + +Nodemon стежитиме за вашим файлом `bot.ts` і перезапускатиме бота при кожній зміні коду. + +## Розгортання + +1. Створіть репозиторій на GitHub, він може бути як приватним, так і публічним. +2. Завантажте свій код. + +> Рекомендується мати одну стабільну гілку і виконувати тестування в окремих гілках, щоб не допустити непередбачуваної поведінки у продакшні. + +3. Відвідайте свою [панель керування Cyclic](https://app.cyclic.sh). +4. Натисніть "Link Your Own" і виберіть свій репозиторій. +5. Перейдіть в "Advanced" > "Variables" і додайте свій `BOT_TOKEN`. +6. Розгорніть свого бота, натиснувши "Connect Cyclic". + +### Встановлення URL-адреси вебхука + +Якщо ви використовуєте вебхуки, після першого розгортання вам слід налаштувати параметри вебхука, щоб він вказував на ваш застосунок. +Для цього надішліть запит на адресу + +```text +https://api.telegram.org/bot<токен-бота>/setWebhook?url=<адреса> +``` + +замінивши `<токен-бота>` на токен вашого бота, а `<адреса>` --- на повну URL-адресу вашого застосунку разом з шляхом до обробника вебхуків. + +Вітаємо! +Тепер ваш бот має бути готовий до роботи. diff --git a/site/docs/zh/hosting/comparison.md b/site/docs/zh/hosting/comparison.md index 2f49c169f..9e9fc8e68 100644 --- a/site/docs/zh/hosting/comparison.md +++ b/site/docs/zh/hosting/comparison.md @@ -49,6 +49,7 @@ Serverless 和 PaaS 有一个缺点,默认情况下不会为你提供持久存 | Scaleway Functions | 免费 | €0.15/1M req, €1.2/100K GB-s | [1M requests, 400K GB-s/mo](https://www.scaleway.com/en/pricing/?tags=serverless-functions-serverlessfunctions) | ❓ | ❓ | ❓ | | | Scaleway Containers | 免费 | €0.10/100K GB-s, €1.0/100K vCPU-s | [400K GB-s, 200K vCPU-s/mo](https://www.scaleway.com/en/pricing/?tags=serverless-containers-serverlesscontainers) | ❓ | ❓ | ❓ | | | Vercel Edge Functions | 免费 | $20/月的订阅, 包含 500K 请求 | [100K req/day](https://vercel.com/pricing) | [✅](https://vercel.com/docs/concepts/functions/edge-functions/edge-runtime#compatible-node.js-modules) | ❓ | [✅](https://vercel.com/templates/edge-functions) | | +| Cyclic.sh | 免费 | 每个 app $1/月,$0.50/100K | [10K req/mo](https://docs.cyclic.sh/overview/limits) | ✅ | ❓ | ❓ | | | serverless.com | 免费 | | | ❓ | ❓ | ❓ | | | Heroku | $5 | $5 for 1,000 [dyno hours](https://devcenter.heroku.com/articles/usage-and-billing#dyno-usage-and-costs)/mo | [512MB RAM, 30分钟不活跃后休眠](https://www.heroku.com/pricing) | ✅ | ✅ | ❓ | Deno is supported by a [third-party buildpack](https://github.com/chibat/heroku-buildpack-deno). | | DigitalOcean Apps | $5 | | | ❓ | ❓ | ❓ | 未测试 | diff --git a/site/docs/zh/hosting/cyclic.md b/site/docs/zh/hosting/cyclic.md new file mode 100644 index 000000000..bcaca7e33 --- /dev/null +++ b/site/docs/zh/hosting/cyclic.md @@ -0,0 +1,158 @@ +--- +prev: false +next: false +--- + +# 托管: Cyclic + +本指南告诉你如何在 [Cyclic](https://cyclic.sh) 上托管 grammY bot。 + +## 先决条件 + +你需要一个 [Github](https://github.com) 账号和一个 [Cyclic](https://cyclic.sh) 账号。 +首先,初始化你的项目并安装一些依赖: + +```sh +# 初始化项目 +mkdir grammy-bot +cd grammy-bot +npm init -y + +# 安装主要依赖 +npm install grammy express dotenv + +# 安装开发依赖 +npm install -D typescript ts-node nodemon @types/express @types/node + +# 初始化 Typescript 配置 +npx tsc --init +``` + +我们将把 Typescript 文件储存在 `src/` 目录下,编译好的文件在 `dist/` 目录下。 +在创建了这两个文件夹后,切换目录到 `src/`,并创建一个名为 `bot.ts` 的文件。 + +```asciiart:no-line-numbers +. +├── node_modules/ +├── dist/ +├── src/ +│ └── bot.ts +├── package.json +├── package-lock.json +└── tsconfig.json +``` + +然后,打开 `tsconfig.json`,用以下配置替换里面的内容: + +```json +{ + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "esModuleInterop": true, + "skipLibCheck": true, + "strict": true + } +} +``` + +之后我们需要添加 `start`,`build` 和 `dev` 脚本到 `package.json` 中。 +我们的 `package.json` 应该类似于这样: + +```json{6-10} +{ + "name": "grammy-bot", + "version": "1.0.0", + "description": "", + "main": "dist/bot.js", + "scripts": { + "build": "tsc", + "start": "node dist/bot.js", + "dev": "nodemon src/bot.ts" + }, + "license": "ISC", + "dependencies": { + "express": "^4.18.2", + "grammy": "^1.17.2", + "dotenv": "^16.3.1" + }, + "devDependencies": { + "@types/express": "^4.17.17", + "@types/node": "^20.4.9", + "typescript": "^5.1.6", + "nodemon": "^3.0.1", + "ts-node": "^10.9.1" + }, + "keywords": [] +} +``` + +### Webhooks + +打开 `src/bot.ts` 并输入以下内容: + +```ts{15} +import express from "express"; +import { Bot, webhookCallback } from "grammy"; +import "dotenv/config"; + +const bot = new Bot(process.env.BOT_TOKEN || ""); + +bot.command("start", (ctx) => ctx.reply("Hello World!")) + +if (process.env.NODE_ENV === "DEVELOPMENT") { + bot.start(); +} else { + const port = process.env.PORT || 3000; + const app = express(); + app.use(express.json()); + app.use(`/${bot.token}`, webhookCallback(bot, "express")); + app.listen(port, () => console.log(`listening on port ${port}`)); +} +``` + +我们建议你将 webhook 处理程序放在秘密路径上,而不是 `/`。 +如上面突出显示的行所示,我们使用 `/` 而不是 `/`。 + +### 本地开发 + +在你的项目的根目录下创建一个包含以下内容的 `.env` 的文件: + +``` +BOT_TOKEN= +NODE_ENV=DEVELOPMENT +``` + +之后,运行你的 `dev` 脚本: + +```sh +npm run dev +``` + +Nodemon 将监视你的 `bot.ts` 文件,并在每次代码更改时重新启动你的 bot。 + +## 部署 + +1. 在 Github 上创建一个仓库,可以是私有的也可以是公开的。 +2. 推送你的代码。 + +> 建议你有一个的稳定分支,以及在单独的分支中进行测试,这样就不会在生产环境中出现意外的行为。 + +3. 访问你的 [Cyclic dashboard](https://app.cyclic.sh)。 +4. 点击 “Link Your Own” 并选择你的仓库。 +5. 跳转到 Advanced > Variables,并添加你的 `BOT_TOKEN`。 +6. 点击 “Connect Cyclic” 部署你的 bot。 + +### 设置 Webhook URL + +如果你使用的是 webhook,则在首次部署后,你应该将 bot 的 webhook 设置配置为指向你的应用程序。 +为此,请发送请求至 + +```text +https://api.telegram.org/bot/setWebhook?url=/ +``` + +将 `` 替换为你的 bot token,将 `` 替换为应用程序的完整 URL 以及 webhook 处理程序的路径。 + +恭喜! +你的 bot 现在应该已启动并运行。