Hosting: Fly
Halaman ini berisi panduan mengenai cara-cara meng-hosting bot di Fly, baik menggunakan Deno maupun Node.js.
Menyiapkan Kode
Kamu bisa menjalankan bot menggunakan webhooks ataupun long polling.
Webhooks
Ingat! Jangan panggil
bot
di kode kamu ketika menggunakan webhooks..start()
- Pastikan kamu meng-export object
Bot
di dalam sebuah file agar nantinya bisa di-import ketika ingin menjalankannya. - Buat sebuah file dengan nama
app
atau.ts app
, ataupun nama lainnya sesuai dengan keinginanmu (tetapi kamu harus mengingatnya karena nanti file tersebut akan digunakan sebagai file deploy utama). File tersebut berisikan:.js
import { webhookCallback } from "https://deno.land/x/grammy@v1.30.0/mod.ts";
// Kamu mungkin perlu mengubah ini agar object bot-mu bisa di-import.
import { bot } from "./bot.ts";
const port = 8000;
const handleUpdate = webhookCallback(bot, "std/http");
Deno.serve({ port }, async (req) => {
const url = new URL(req.url);
if (req.method === "POST" && url.pathname.slice(1) === bot.token) {
try {
return await handleUpdate(req);
} catch (err) {
console.error(err);
}
}
return new Response();
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import express from "express";
import { webhookCallback } from "grammy";
// Kamu mungkin perlu mengubah ini agar object bot-mu bisa di-import.
import { bot } from "./bot";
const port = 8000;
const app = express();
app.use(express.json());
app.use(`/${bot.token}`, webhookCallback(bot, "express"));
app.use((_req, res) => res.status(200).send());
app.listen(port, () => console.log(`listening on port ${port}`));
2
3
4
5
6
7
8
9
10
11
12
13
Kami menganjurkan kamu untuk menaruh handler di direktori rahasia alih-alih menempatkanya di root (/
). Di contoh kali ini, kita menggunakan token bot (/<token bot>
) sebagai direktori rahasianya (perhatikan baris kode yang disorot).
Long Polling
Buat sebuah file dengan nama app
atau app
, ataupun nama lainnya sesuai dengan keinginanmu (tetapi kamu harus mengingatnya karena nanti file tersebut akan digunakan sebagai file deploy utama). File tersebut berisikan:
import { Bot } from "https://deno.land/x/grammy@v1.30.0/mod.ts";
const token = Deno.env.get("BOT_TOKEN");
if (!token) throw new Error("BOT_TOKEN belum diisi");
const bot = new Bot(token);
bot.command(
"start",
(ctx) => ctx.reply("Aku berjalan di Fly menggunakan long polling!"),
);
Deno.addSignalListener("SIGINT", () => bot.stop());
Deno.addSignalListener("SIGTERM", () => bot.stop());
bot.start();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Bot } from "grammy";
const token = process.env.BOT_TOKEN;
if (!token) throw new Error("BOT_TOKEN belum diisi");
const bot = new Bot(token);
bot.command(
"start",
(ctx) => ctx.reply("Aku berjalan di Fly menggunakan long polling!"),
);
process.once("SIGINT", () => bot.stop());
process.once("SIGTERM", () => bot.stop());
bot.start();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Perhatikan baris kode yang disorot di atas, kita telah mengambil informasi sensitif (token bot kamu) dari environment variables. Kamu bisa menyimpan informasi tersebut dengan menjalankan perintah berikut:
flyctl secrets set BOT_TOKEN="AAAA:12345"
Dengan cara yang sama, kamu bisa menyimpan informasi sensitif lainnya. Kunjungi https://
Men-deploy Bot
Metode 1: Menggunakan flyctl
Metode ini adalah cara yang termudah.
Jalankan
flyctl launch
untuk membuat sebuah fileDockerfile
danfly
yang nantinya untuk digunakan saat deployment. Tetapi, JANGAN di-deploy terlebih dahulu..toml shflyctl launch
1logCreating app in /my/telegram/bot Scanning source code Detected a Deno app ? App Name (leave blank to use an auto-generated name): grammy Automatically selected personal organization: CatDestroyer ? Select region: ams (Amsterdam, Netherlands) Created app grammy in organization personal Wrote config file fly.toml ? Would you like to set up a Postgresql database now? No ? Would you like to deploy now? No Your app is ready. Deploy with `flyctl deploy`
1
2
3
4
5
6
7
8
9
10
11shflyctl launch
1logCreating app in /my/telegram/bot Scanning source code Detected a NodeJS app Using the following build configuration: Builder: heroku/buildpacks:20 ? App Name (leave blank to use an auto-generated name): grammy Automatically selected personal organization: CatDestroyer ? Select region: ams (Amsterdam, Netherlands) Created app grammy in organization personal Wrote config file fly.toml ? Would you like to set up a Postgresql database now? No ? Would you like to deploy now? No Your app is ready. Deploy with `flyctl deploy`
1
2
3
4
5
6
7
8
9
10
11
12
13Deno: Ubah versi Deno dan hapus
CMD
di dalam fileDockerfile
. Pada contoh di bawah, kami mengubahDENO
menjadi_VERSION 1
..25 .2 Node.js: Untuk mengubah versi Node.js, kamu perlu menambahkan property
node
ke dalam propertyengine
yang berada di dalam filepackage
. Pada contoh di bawah, kami mengubah versi Node.js menjadi.json 16
..14 .0 dockerfile# Dockerfile ARG DENO_VERSION=1.25.2 ARG BIN_IMAGE=denoland/deno:bin-${DENO_VERSION} FROM ${BIN_IMAGE} AS bin FROM frolvlad/alpine-glibc:alpine-3.13 RUN apk --no-cache add ca-certificates RUN addgroup --gid 1000 deno \ && adduser --uid 1000 --disabled-password deno --ingroup deno \ && mkdir /deno-dir/ \ && chown deno:deno /deno-dir/ ENV DENO_DIR /deno-dir/ ENV DENO_INSTALL_ROOT /usr/local ARG DENO_VERSION ENV DENO_VERSION=${DENO_VERSION} COPY --from=bin /deno /bin/deno WORKDIR /deno-dir COPY . . ENTRYPOINT ["/bin/deno"] # CMD tidak digunakan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26json// package.json { "name": "grammy", "version": "1.0.0", "description": "grammy", "main": "app.js", "author": "itsmeMario", "license": "MIT", "dependencies": { "express": "^4.18.1", "grammy": "^1.11.0" }, "devDependencies": { "@types/express": "^4.17.14", "@types/node": "^18.7.18", "typescript": "^4.8.3" }, "engines": { "node": "16.14.0" } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21Ubah
app
di dalam filefly
. Path.toml .
(atau/app .ts .
untuk Node.js) pada contoh di bawah mengacu pada direktori file utamanya. Kamu mungkin perlu mengaturnya agar sesuai dengan direktori proyek kamu. Kalau kamu menggunakan webhooks, pastikan port-nya sama dengan konfigurasi yang kamu miliki, dalam hal ini port-nya adalah/app .js 8000
.toml# fly.toml app = "grammy" kill_signal = "SIGINT" kill_timeout = 5 [processes] app = "run --allow-net ./app.ts" [[services]] http_checks = [] internal_port = 8000 processes = ["app"] protocol = "tcp" script_checks = [] [services.concurrency] hard_limit = 25 soft_limit = 20 type = "connections" [[services.ports]] force_https = true handlers = ["http"] port = 80 [[services.ports]] handlers = ["tls", "http"] port = 443 [[services.tcp_checks]] grace_period = "1s" interval = "15s" restart_limit = 0 timeout = "2s"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33toml# fly.toml app = "grammy" kill_signal = "SIGINT" kill_timeout = 5 [processes] app = "run --allow-net ./app.ts" # Hapus semua bagian [[services]] karena kita tidak perlu menyimak HTTP
1
2
3
4
5
6
7
8
9toml# fly.toml app = "grammy" kill_signal = "SIGINT" kill_timeout = 5 [processes] app = "node ./build/app.js" # Atur environment variable NODE_ENV agar tidak muncul peringatan atau warning [build.args] NODE_ENV = "production" [build] builder = "heroku/buildpacks:20" [[services]] http_checks = [] internal_port = 8000 processes = ["app"] protocol = "tcp" script_checks = [] [services.concurrency] hard_limit = 25 soft_limit = 20 type = "connections" [[services.ports]] force_https = true handlers = ["http"] port = 80 [[services.ports]] handlers = ["tls", "http"] port = 443 [[services.tcp_checks]] grace_period = "1s" interval = "15s" restart_limit = 0 timeout = "2s"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40toml# fly.toml app = "grammy" kill_signal = "SIGINT" kill_timeout = 5 [processes] app = "node ./build/app.js" # Atur environment variable NODE_ENV agar tidak muncul peringatan atau warning [build.args] NODE_ENV = "production" [build] builder = "heroku/buildpacks:20" # Hapus semua bagian [[services]] karena kita tidak perlu menyimak HTTP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16Jalankan
flyctl deploy
untuk men-deploy kode kamu.
Metode 2: Dengan GitHub Actions
Kelebihan dari metode ini adalah Fly akan selalu memantau perubahan di repositori tempat kamu menaruh kode bot. Ketika terjadi perubahan, kode tersebut akan di-deploy secara otomatis ke versi yang lebih baru. Untuk instruksi detailnya, silahkan kunjungi https://
Dapatkan token API Fly dengan cara menjalankan perintah
flyctl auth token
.Buat sebuah repositori di GitHub, bisa berupa privat ataupun publik.
Pergi ke Settings, pilih Secrets dan buat sebuah secret bernama
FLY
yang berisi nilai atau value token dari langkah ke-2._API _TOKEN Buat
.github
, kemudian isi dengan kode berikut:/workflows /main .yml ymlname: Fly Deploy on: [push] env: FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} jobs: deploy: name: Deploy app runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: superfly/flyctl-actions/setup-flyctl@master - run: flyctl deploy --remote-only
1
2
3
4
5
6
7
8
9
10
11
12Ikuti langkah 2 hingga 4 dari Metode 1 di atas. Jangan lupa untuk melewati langkah terakhir (step 5) karena kita tidak ingin men-deploy kode secara langsung.
Commit perubahan kamu, lalu push ke GitHub.
Di sinilah keajaibannya mulai terjadi—push tadi akan memicu sebuah deploy dan mulai sekarang kapanpun kamu melakukan push, kode tersebut akan secara otomatis di deploy ulang.
Mengatur URL Webhook
Setelah mendapati bot-mu dapat berjalan, kamu harus melakukan konfigurasi pada pengaturan webhook untuk menggunakan URL bot-mu yang baru. Untuk melakukannya, kirim sebuah request ke
https://api.telegram.org/bot<token>/setWebhook?url=<url>
Ganti <token>
dengan token bot-mu, dan <url>
dengan URL lengkap bot kamu.
Optimisasi Dockerfile
Ketika Dockerfile
kamu dijalankan, ia akan menyalin semua file ke Docker image. Untuk aplikasi Node.js, beberapa direktori seperti node
akan dibikin ulang sehingga direktori tersebut tidak perlu disalin. Untuk melakukannya, buat sebuah file .dockerignore
lalu tambahkan node
ke dalamnya. Kamu juga bisa menggunakan .dockerignore
untuk mencegah file-file yang tidak diperlukan ikut tersalin saat di runtime.