Telegram Serverless, Telegram’ın altyapısında botunuz ve Mini Uygulamanız için arka uç kodunu çalıştırmanızı sağlar — sunucu hazırlamanıza, canlı tutacak kapsayıcılar çalıştırmanıza veya ölçeklendirmeyi düşünmenize gerek yok. Düz JavaScript modülleri yazarsınız, tek bir komutla dağıtırsınız ve Telegram bunları Bot API’sinin hemen yanında bulunan hızlı, izole bir V8 sanal alanında çalıştırır ve yerleşik bir veritabanı sunar.
Bir /start komutuna yanıt vermek için bir botu bir VPS’ye, bir bulut işlevine veya bir barındırma paneline bağladıysanız, artık yapmanız gerekmeyen kısım budur.
Neden sunucusuz
Telegram botu, özünde güncellemelere tepki veren bir programdır. Geleneksel olarak bu programı her zaman açık, erişilebilir ve güvenli bir yere barındırmanız ve sonra bunu öyle tutmanız gerekirdi. Telegram Serverless bu katmanı tamamen ortadan kaldırır:
- Altyapı yok. Kiralanacak, yamalanacak veya izlenecek makine yok. Kodunuz isteğe bağlı olarak çalışır ve botunuzla otomatik olarak ölçeklenir.
- Kimlik bilgileri dahil. Telegram Bot API, SQLite destekli bir veritabanı ve giden HTTP, kutudan çıktığı gibi her modüle kullanılabilir — kurulacak bir şey yok, bağlanacak kimlik bilgisi yok.
- Hızlı, izole yürütme. Her çağrı, hafif bir V8 izole parçacığında, Telegram’ın kendi sistemlerine yakın çalışır, böylece Bot API’sine ve veritabanınıza yapılan çağrılar hızlı ve güvenilirdir.
- Gerçek bir geliştirici iş akışı. Bir proje, sürüm denetimi altında makinenizdeki bir klasörde yaşar. Dosyaları düzenler, neyin değiştiğini tam olarak görür, atomik olarak dağıtır ve veritabanı şemanızı gözden geçirilmiş geçişlerle ileriye doğru yuvarlarsınız — zaten diğer her şeyle çalıştığınız şekilde.
Zihinsel model: Proje nasıl çalışır
Üç yerde çalışırsınız ve bunlar birbirine temiz bir şekilde eşlenir:
| Nerede | Orada ne yaşar |
|---|---|
| Proje klasörünüz | JavaScript modülleri — şema, paylaşılan kod, güncelleme işleyicileri, Mini Uygulama uç noktaları — ve eğer varsa, Mini Uygulamanın ön ucu |
| Bulut | Bu modüllerin dağıtılmış kopyası, botunuzun veritabanı ve Mini Uygulamanın dosyaları |
tgcloud CLI’si |
Köprü — farkları gösterir ve bunları senkronize eder |
Hiçbir şeye SSH yapmazsınız. Dosyaları yerel olarak düzenler, npx tgcloud push çalıştırır ve platform gerisini halleder. Botunuzun trafiği dağıtılmış modüller tarafından işlenir; veritabanınız çağrılar arasında kalıcı olur.
Bir projenin yalnızca dört tür kodu vardır, hepsi tek bir tgcloud/ klasörünün içinde:
tgcloud/
├─ endpoints/ # Mini Uygulamanızın çağırdığı işlevler
├─ handlers/ # Telegram güncelleme türlerine tepki veren işlevler
├─ lib/ # Her yerden içe aktardığınız paylaşılan kod
└─ schema.js # veritabanı tablolarınız
Bir güncelleme geldiğinde — bir mesaj, bir düğme basımı, bir satır içi sorgu — Telegram bunu eşleşen işleyiciye (handlers/message.js, handlers/callback_query.js, …) yönlendirir ve varsayılan dışa aktarımını çağırır. Bu işlev, SDK aracılığıyla Bot API’si ve veritabanıyla konuşur ve geri döner. Bütün döngü budur. Eşleşen bir işleyicisi olmayan bir güncelleme basitçe göz ardı edilir, bu nedenle yalnızca ihtiyacınız olan işleyicileri eklersiniz.
Mini Uygulama isteğe bağlıdır. Botunuzun bir tane varsa, ön ucu aynı projede, tgcloud/‘nin yanında bulunur. Sunucusuz, oluşturulan çıktısını barındırır ve çağırdığı endpoints/‘leri çalıştırır. Bkz.
Mini Uygulama ön ucu
.
Hızlı demo
İşte eksiksiz, çalışan bir demo bot. Her mesaja yanıt verir ve her sohbetten kaç tane gördüğünü hatırlar.
tgcloud/schema.js
import { table, integer } from 'sdk/db';
export const counters = table('counters', {
chatId: integer('chat_id').primaryKey() ,
seen: integer('seen').notNull().default(0) ,
});
tgcloud/handlers/message.js
import { api, db } from 'sdk';
import { sql } from 'sdk/db';
import { counters } from '../schema.js';
export default async function (message) {
const chatId = message.chat.id;
// Sayacı ekleyin veya bu sohbetin zaten bir tane varsa artırın — ve
// aynı deyimde geri dönen satırı .returning() aracılığıyla alın.
const [row] = await db.insert(counters)
.values({ chatId, seen: 1 })
.onConflictDoUpdate({
target: counters.chatId,
set: { seen: sql`${counters.seen} + 1` },
})
.returning()
.run();
await api.sendMessage({
chat_id: chatId,
text: `Merhaba! Senden ${row.seen} mesaj gördüm.`,
});
}
Dağıtın:
npx tgcloud push # modülleri yükle
npx tgcloud migrate # `counters` tablosunu oluştur
Bu, kalıcı duruma ve sunucuya sahip canlı bir bottur. İçindeki her şey — api, db, table() DSL’si — aşağıdaki bölümlerde açıklanmıştır.
Serverless, bir tür uygulama için bir şablon değil, Telegram botları ve Mini Uygulamalar için genel bir arka uçtur. Şu durumlar için idealdir:
- Konuşma Yapay Zeka Botları kullanıcı başına durumu bir veritabanında saklaması gereken.
- Mini Uygulama Arka Uçları kullanıcı verilerini saklayan ve dinamik içerik sunan.
- Oyunlar ve Araçlar — liderlik tabloları, bilgi yarışmaları ve daha fazlası dahil.
- Otomasyonlar ve Entegrasyonlar üçüncü taraf HTTP API’lerini çağıran ve sonuçları sohbetlere gönderen.
Başlarken
Bu adım adım kılavuz sizi boş bir klasörden mesajlara yanıt veren ve veri depolayan canlı bir bota götürür.
Node.js
18 veya daha yenisinin yüklü olduğunu ve
@BotFather
ile kayıtlı bir botunuz olduğunu varsayar. Sonunda, her gün ihtiyaç duyacağınız tüm komutları kullanacaksınız: push, migrate, run ve status.
Her şeyden önce, Serverless’ı açın. @BotFather ‘da botunuz → Serverless ‘ı açın ve açın. Bu, bu bot için özelliği açar ve CLI erişim jetonu, işleyicileri, kitaplığı ve veritabanını etkinleştirir.
1. Bir proje oluşturun
Başlamanın en hızlı yolu, bir projeyi oluşturan ve CLI’yı içine yükleyen proje yaratıcısıdır:
npm create @tgcloud/bot example_bot
cd example_bot
Argüman hedef klasördür: geçerli klasöre yerleştirmek için . geçirin veya herhangi bir yol. Mevcut bir klasörde de çalışır ve asla sahip olduğunuz dosyaları üzerine yazmaz.
Bu size düzenlenmeye hazır bir proje verir:
example_bot/
├─ tgcloud/ # platformun çalıştırdığı her şey
│ ├─ handlers/
│ │ └─ message.js # bir başlangıç mesajı işleyicisi (metni geri yankılar)
│ ├─ lib/ # paylaşılan modülleriniz buraya gider (başlangıçta boş)
│ └─ schema.js # veritabanı tablolarınız
├─ docs/
│ └─ tgcloud-sdk.md # SDK referansı (sizin ve yapay zeka araçlarınız için)
├─ AGENTS.md # yapay zeka kodlama yardımcıları için yönlendirme
├─ package.json
└─ tgcloud.jsonc # proje yapılandırması
Oluşturulan dosyalar kendi kendine belgelenir — her biri ne yapabileceğinize dair yorumlanmış örnekler içerir.
CLI, projeye yerel bir geliştirme bağımlılığı olarak yüklenir, bu nedenle npx tgcloud <command> ile çalıştırırsınız (npx projenizin node_modules içindeki kopyayı bulur) veya package.json‘a eklediği kısayollar aracılığıyla (npm run deploy, npm run status). Varsayılan olarak PATH‘inizde küresel bir tgcloud yoktur.
İsterseniz küresel olarak da yükleyebilirsiniz — npm install -g @tgcloud/cli — herhangi bir yerden çıplak tgcloud yazmayı tercih ederseniz. Bu, herhangi bir boş klasörde tgcloud init çalıştırmak için kullanışlıdır ve kabuk sekme tamamlama için gereken şeydir. Her iki durumda da aynı projeyi elde edersiniz.
Bir Mini Uygulama mı geliştiriyorsunuz? Bunun yerine ön ucundan başlayın. Onu standart aracınızla oluşturun, sonra proje yaratıcısını o klasörde çalıştırın. Bkz. Mini Uygulama ön ucu .
2. Botunuzu bağlayın
Her proje tek bir bota bağlıdır. login ile bağlayın; bu, CLI erişim jetonunuzu ister (
@BotFather
→ botunuz → Serverless → CLI Access → Access token — botunuzun
API jetonundan
ayrı bir jeton) ve onu yerel olarak depolar:
npx tgcloud login
Jeton app<id>:<secret> biçimindedir. CLI, bunu .tgcloud/‘de saklar, git’ten yok sayılır ve gizli bölümü asla yazdırmaz. Giriş, sizden istendiği tek zamandır — CI’da jetonların nasıl çözümlendiği için bkz.
Kimlik doğrulama
.
3. Göz atın
İki komut herhangi bir anda nelerin olup bittiğini size bildirir, her ikisi de tamamen çevrimdışı çalışır:
npx tgcloud status # yerel olarak neyin değiştiği vs. dağıtılmış kopya
npx tgcloud diff # satır satır değişiklikler
init yaptıktan hemen sonra her şey yenidir ve henüz hiçbir şey dağıtılmamıştır. status, yüklenmeyi bekleyen başlangıç dosyalarını gösterir.
4. Dağıtın
Modüllerinizi buluta gönderin:
npx tgcloud push
push, değiştirilen her modülü atomik bir toplu işlemde yükler ve bulutun şu anda neleri tuttuğuna dair yerel kaydınızı günceller. Botunuz canlı: Telegram’da açın ve ona bir mesaj gönderin — başlangıç işleyicisi onu geri yankılar.
Dağıtım asla veritabanınıza dokunmaz. Kod dağıtımı ve veritabanı şemanızı değiştirme işlemleri kasıtlı olarak ayrı adımlardır, bu nedenle bir kod dağıtımı sizi asla bir veri geçişiyle şaşırtamaz. Bir sonraki adım bunun içindir.
5. Bir veritabanı tablosu ekleyin
Botun bir şeyi hatırlamasını sağlayalım. tgcloud/schema.js dosyasını açın ve bir tablo bildirin:
import { table, integer, text, sql } from 'sdk/db';
export const messages = table('messages', {
id: integer('id').primaryKey({ autoIncrement: true }) ,
chatId: integer('chat_id').notNull() ,
text: text('text') ,
created: integer('created_at', { mode: 'timestamp' }).default(sql`(unixepoch())`) ,
});
Şemayı dağıtın, sonra veritabanına uygulayın:
npx tgcloud push # yeni şemayı yükler
npx tgcloud migrate # `messages` tablosunu oluşturur
push, şemanın senkronize olmadığını bildirir ve bekleyen değişikliği size gösterir, ancak hiçbir şeyi uygulamaz. migrate, değişikliği size adım adım gösterir ve onayınız üzerine tabloyu oluşturur. Bu iki adımlı model — ve daha riskli değişiklikler (örneğin silmeler) olduğunda ne olduğu —
Geçişler
bölümünde ele alınır.
6. Veri depolayın ve okuyun
Şimdi tabloyu işleyicinizden kullanın. tgcloud/handlers/message.js dosyasını düzenleyin:
import { api, db } from 'sdk';
import { eq } from 'sdk/db';
import { messages } from '../schema.js';
export default async function (message) {
// Bu mesajı kaydedin.
await db.insert(messages)
.values({ chatId: message.chat.id, text: message.text })
.run();
// Bu sohbet için kaç tane depoladığımızı sayın.
const count = await db.$count(messages, eq(messages.chatId, message.chat.id));
await api.sendMessage({
chat_id: message.chat.id,
text: `Kaydedildi. Bu sohbetten şimdiye kadar ${count} mesajınız var.`,
});
}
Güncellenen işleyiciyi npx tgcloud push ile dağıtın, ardından botunuza birkaç mesaj gönderin ve sayacın yükselişini izleyin. Veritabanı çağrılar arasında kalıcıdır — bu botunuzun hafızasıdır.
7. Dağıtım yapmadan test edin
Bir değişikliği denemek için dağıtım yapmak zorunda değilsiniz. npx tgcloud run, dağıtım yapmadan platformda işleyiciyi yerel dosyalarınızı kullanarak yürütür:
npx tgcloud run handlers/message '{ chat: { id: 1 }, text: "merhaba" }'
Argüman, işleyicinizin aldığı yüktür — handlers/message için, bir
Mesaj
—
JSON5
biçiminde (bu nedenle anahtarları alıntılamayı atlayabilirsiniz). Komut, console.* ile günlüğe kaydettiğiniz her şeyi, geri dönen değeri ve ne kadar sürdüğünü yazdırır. Bu, mantık üzerinde yinelemek için en sıkı döngüdür — dağıtım yok, gerçek bir mesaj beklemek yok.
8. Senkronize kalın
Çalışırken, birkaç komut yerel projenizi ve bulutu uyumlu tutar: npx tgcloud status neyin değiştiğini gösterir, npx tgcloud push dağıtır, npx tgcloud pull yerel projenizi buluta uyumlu hale getirir, npx tgcloud fetch dosyalarınızı etkilemeden dağıtılmış olanları kontrol eder ve npx tgcloud reset yerel değişiklikleri atar.
Aynı bota iki kişi (veya iki makine) dağıtım yaparsa, platform çakışmayı algılar ve
pushsizi öncepullyapmaya bırakmak için durur — başkasının çalışmasını asla sessizce üzerine yazamazsınız. Bkz. Senkronize Kalma .
Yapay zeka ile geliştirme
Bir yapay zeka asistanıyla oluşturmayı mı tercih ediyorsunuz — veya ekibinizdeki tek kodlayıcı bir yapay zeka mı? Yine de bir bot gönderebilirsiniz. Bir yapay zeka ajanının projede kendine yer bulmasını sağlamak için ilk adımı attık: her yeni proje AGENTS.md ve ajan kodlama araçlarının otomatik olarak okuduğu docs/tgcloud-sdk.md referansı ile oluşturulur.
Küçük, kendi kendine yeten bir çalışma zamanıyla birlikte — tek bir SDK, uğraşılacak npm paketi yok — bu, ajana genel kod üretiminin burada kaçırdığı geleneklere göre iyi bir başlangıç sağlar: .js ile göreceli içe aktarmalar, yabancı anahtar yok, her db çağrısı asenkrondur, güncelleme türü başına bir işleyici ve iki adımlı push/migrate akışı.
Dene:
npm create @tgcloud/bot my-bot
cd my-bot
opencode # veya Claude Code, Cursor, … — AGENTS.md'yi okuyan herhangi bir ajan
Sonra sadece düz bir dilde sorun:
Her kişinin yapılacaklar listesini hatırlayan bir bot yazın — metin gönderdiklerinde bir öğe ekleyin ve /list gönderdiklerinde tüm listeyi gösterin.
Asistan schema.js ve işleyicilerinizi sizin için düzenler; gözden geçirir, bir değişikliği npx tgcloud run ile anında test eder, ardından npx tgcloud push ve npx tgcloud migrate ile canlıya geçersiniz. AGENTS.md projenizin bir parçasıdır — bot büyüdükçe rehberliğin doğru kalması için onu düzenleyin.
BotFather ile hareket halinde
Sadece telefonunuz mu var? Tüm proje @BotFather içinde de yaşar — botunuzu açın → Serverless ve CLI’nin yönettiği her şeyi bir dokunmatik ekranda alırsınız:
- İşleyiciler — güncelleme işleyicileri oluşturun, düzenleyin ve test edin; BotFather, webhook’u sahip olduğunuz işleyicilerle senkronize tutar (CLI’nin bildirdiği Senkronize/ Senkronize Değil ile aynı).
- Uç Noktalar — Mini Uygulamanızın çağırdığı işlevler.
- Kitaplık — paylaşılan
lib/modülleriniz. - Veritabanı — aynı Drizzle benzeri sözdiziminde
schema.js‘yi düzenleyin, bekleyen değişiklikleri gözden geçirin ve uygulayın; Kaydet dağıtır. - Mini Uygulama Dosyaları — kullanıcılarınızın Telegram’da açtığı ön uç.
- CLI Erişimi — klavyeye geri döndüğünüzde CLI erişim jetonunu buradan alın.
Bu aynı bulut projesidir, bu nedenle bir işleyiciyi telefonunuzda başlatıp daha sonra dizüstü bilgisayarınıza npx tgcloud pull yapabilirsiniz — hiçbir şey tek bir istemciye bağlı değildir. Bir işleyiciyi çalıştırmak bile,
npx tgcloud run
gibi Konsol çıktısını sohbetin içinde gösterir.
Projeler ve modüller
Sunucusuz proje, sürüm denetimi altında sıradan bir klasördür. Platformun çalıştırdığı her şey tek bir klasörde, tgcloud/‘de bulunur; projenin geri kalanı size aittir — bir mini uygulama ön ucu, yapılandırma, belgeler. Bot için bir derleme adımı, çalışma zamanında node_modules ve bir sunucu giriş noktası yoktur.
Proje yapısı
example_bot/
├─ tgcloud/ # dağıtılmış kısım — başka hiçbir şey değil
│ ├─ handlers/ # güncelleme işleyicileri — düz, yalnızca tek seviye
│ │ ├─ message.js
│ │ └─ callback_query.js
│ ├─ endpoints/ # Mini Uygulamanızın çağırdığı işlevler — düz, yalnızca tek seviye
│ │ └─ getProfile.js
│ ├─ lib/ # paylaşılan modüller; alt dizinlere izin verilir
│ │ ├─ reply.js
│ │ └─ internal/util.js
│ └─ schema.js # veritabanı şeması — tek dosya
└─ .tgcloud/ # CLI durumu, git'ten yok sayılır
tgcloud/ içindeki yalnızca .js dosyaları — schema.js, lib/, handlers/, endpoints/ — dağıtılır. Diğer her şey — Markdown, yapılandırma dosyaları, .tgcloud/ klasörü, tgcloud/ dışındaki her şey — makinenizde kalır. Modül adları tgcloud/‘ye göreceli olur. tgcloud/handlers/message.js dosyası handlers/message modülüdür ve npx tgcloud run‘ın aldığı ad budur.
Eski bir projeden mi yükseltiyorsunuz? CLI 0.2.0’dan önceki projeler
schema.js,lib/vehandlers/‘ı proje kökünde tutuyordu. Onlarıtgcloud/içine taşımak için bir keznpx tgcloud upgradeçalıştırın.
schema.js — veritabanınız. Şema DSL’yi kullanarak tabloları adlandırılmış dışa aktarımlar olarak bildirir ve tgcloud/‘de tek bir dosya olarak bulunur. Herhangi bir modül gibi dağıtılır, ancak dağıtılması asla veritabanını değiştirmez — şema değişiklikleri npx tgcloud migrate ile ayrı olarak uygulanır. Bkz.
Veritabanı
.
lib/ — paylaşılan kod, işleyiciler arasında yeniden kullanmak istediğiniz her şey: saf yardımcılar, veritabanı erişim katmanları, biçimlendirme, dış hizmetlerle entegrasyonlar. lib/ dizini alt dizinler içerebilen tek dizindir (lib/internal/util.js, lib/payments/stripe.js), bu nedenle daha büyük bir kod tabanını istediğiniz gibi düzenleyebilirsiniz. lib/‘deki modüller platform tarafından doğrudan çağrılmaz; işleyiciler ve birbirleri tarafından içe aktarılmak için vardır.
handlers/ — botunuzun giriş noktaları. Her dosya bir Telegram güncelleme türüne karşılık gelir ve platform her gelen güncellemeyi eşleşen işleyiciye yönlendirir:
| Dosya | İşler |
|---|---|
handlers/message.js |
Yeni gelen mesajlar |
handlers/inline_query.js |
Yeni gelen satır içi sorgular |
handlers/callback_query.js |
Yeni gelen geri arama sorguları |
| … | Diğer tüm Bot API güncelleme türleri |
handlers/ düzdür — alt dizin yok. Bir işleyicinin export default‘u, platformun eşleşen güncelleme geldiğinde çağırdığı işlevdir (bkz.
İşleyiciler
).
Bir güncelleme türü, yalnızca işleyici dosyası mevcutsa ve boş değilse işlenir. handlers/<type>.js yoksa — veya dosya boşsa — bu türdeki güncellemeler göz ardı edilir ve platform onlar için hiçbir şey çalıştırmaz. Bu nedenle yalnızca gerçekten ihtiyacınız olan işleyicileri saklayın: eklediğiniz her biri botunuzun işlem yapmak için uyandığı başka bir güncelleme türüdür ve geri kalanları dışarıda bırakmak, Telegram’ın zaten atacağınız güncellemeler için kodunuzu başlatmayacağı anlamına gelir.
Yeni bir işleyici oluşturmak için
npx tgcloud add handlers/<type>çalıştırın.
endpoints/ — Mini Uygulamanızın arka ucu. Her dosya, Mini Uygulamanın adıyla çağırdığı bir işlevdir, bu nedenle endpoints/getProfile.js POST /api/getProfile‘a yanıt verir. Platform, çağrının Mini Uygulamanızdaki bir Telegram kullanıcısından geldiğini kodunuz çalışmadan önce kontrol eder ve size o kullanıcıyı verir. endpoints/ düzdür, handlers/ gibi. Bkz.
Uç Noktalar
.
.tgcloud/ — yalnızca CLI tarafından yönetilen, kaydedilmiş kimlik bilgileriniz dahil makineye özgü durum. Git’ten yok sayılır ve asla elle okunmamalı veya yazılmamalıdır — bunun yerine CLI komutlarını kullanın.
Proje yapısı
example_bot/
├─ tgcloud/ # dağıtılacak kısım — başka hiçbir şey değil
│ ├─ handlers/ # güncelleme işleyicileri — düz, yalnızca tek seviye
│ │ ├─ message.js
│ │ └─ callback_query.js
│ ├─ endpoints/ # Mini Uygulamanızın çağırdığı işlevler — düz, yalnızca tek seviye
│ │ └─ getProfile.js
│ ├─ lib/ # paylaşılan modüller; alt dizinlere izin verilir
│ │ ├─ reply.js
│ │ └─ internal/util.js
│ └─ schema.js # veritabanı şeması — tek dosya
└─ .tgcloud/ # CLI durumu, git'ten yok sayılır
Yalnızca tgcloud/ altındaki .js dosyaları — schema.js, lib/, handlers/, endpoints/ — dağıtılır. Diğer her şey — Markdown, yapılandırma dosyaları, .tgcloud/ klasörü, tgcloud/ dışındaki her şey — makinenizde kalır. Modül adları tgcloud/‘ye göreceli olur. tgcloud/handlers/message.js dosyası handlers/message modülüdür ve npx tgcloud run‘ın aldığı ad budur.
Eski bir projeden mi yükseltiyorsunuz? CLI 0.2.0’dan önceki projeler
schema.js,lib/vehandlers/‘ı proje kökünde tutuyordu. Onlarıtgcloud/içine taşımak için bir keznpx tgcloud upgradeçalıştırın.
schema.js — veritabanınız. Şema DSL’yi kullanarak tabloları adlandırılmış dışa aktarımlar olarak bildirir ve tgcloud/‘de tek bir dosya olarak bulunur. Herhangi bir modül gibi dağıtılır, ancak dağıtılması asla veritabanını değiştirmez — şema değişiklikleri npx tgcloud migrate ile ayrı olarak uygulanır. Bkz.
Veritabanı
.
lib/ — paylaşılan kod, işleyiciler arasında yeniden kullanmak istediğiniz her şey: saf yardımcılar, veritabanı erişim katmanları, biçimlendirme, dış hizmetlerle entegrasyonlar. lib/ dizini alt dizinler içerebilen tek dizindir (lib/internal/util.js, lib/payments/stripe.js), bu nedenle daha büyük bir kod tabanını istediğiniz gibi düzenleyebilirsiniz. lib/‘deki modüller platform tarafından doğrudan çağrılmaz; işleyiciler ve birbirleri tarafından içe aktarılmak için vardır.
handlers/ — botunuzun giriş noktaları. Her dosya bir Telegram güncelleme türüne karşılık gelir ve platform her gelen güncellemeyi eşleşen işleyiciye yönlendirir:
| Dosya | İşler |
|---|---|
handlers/message.js |
Yeni gelen mesajlar |
handlers/inline_query.js |
Yeni gelen satır içi sorgular |
handlers/callback_query.js |
Yeni gelen geri arama sorguları |
| … | Diğer tüm Bot API güncelleme türleri |
handlers/ düzdür — alt dizin yok. Bir işleyicinin export default‘u, platformun eşleşen güncelleme geldiğinde çağırdığı işlevdir (bkz.
İşleyiciler
).
Bir güncelleme türü, yalnızca işleyici dosyası mevcutsa ve boş değilse işlenir. handlers/<type>.js yoksa — veya dosya boşsa — bu türdeki güncellemeler göz ardı edilir ve platform onlar için hiçbir şey çalıştırmaz. Bu nedenle yalnızca gerçekten ihtiyacınız olan işleyicileri saklayın: eklediğiniz her biri botunuzun işlem yapmak için uyandığı başka bir güncelleme türüdür ve geri kalanları dışarıda bırakmak, Telegram’ın zaten atacağınız güncellemeler için kodunuzu başlatmayacağı anlamına gelir.
Yeni bir işleyici oluşturmak için
npx tgcloud add handlers/<type>çalıştırın.
endpoints/ — Mini Uygulamanızın arka ucu. Her dosya, Mini Uygulamanın adıyla çağırdığı bir işlevdir, bu nedenle endpoints/getProfile.js POST /api/getProfile‘a yanıt verir. Platform, çağrının Mini Uygulamanızdaki bir Telegram kullanıcısından geldiğini kodunuz çalışmadan önce kontrol eder ve size o kullanıcıyı verir. endpoints/ düzdür, handlers/ gibi. Bkz.
Uç Noktalar
.
.tgcloud/ — yalnızca CLI tarafından yönetilen, kaydedilmiş kimlik bilgileriniz dahil makineye özgü durum. Git’ten yok sayılır ve asla elle okunmamalı veya yazılmamalıdır — bunun yerine CLI komutlarını kullanın.
Modül sistemi
Çalışma zamanında bir modül tam olarak iki şeyi görebilir: platform SDK’sı ve projenizdeki diğer modüller. npm paketi, dosya sistemi ve SDK’nın fetch‘i dışındaki ağ yoktur.
Herhangi bir JavaScript projesinde olduğu gibi kendi modüllerinizi göreceli yol, .js uzantısıyla içe aktarın — ve SDK’yı adı ile:
// tgcloud/handlers/message.js
import { users } from '../schema.js'; // şema modülü
import { addItem } from '../lib/cart.js'; // bir lib modülü
import { format } from '../lib/internal/fmt.js'; // iç içe lib modülü
import { db, api, fetch } from 'sdk'; // platform SDK'sı
// tgcloud/lib/cart.js
import { format } from './internal/fmt.js'; // bir komşu
import { users } from '../schema.js';
Göreli bir içe aktarma .js ile bitmeli ve tgcloud/ dışına çıkamaz:
import { users } from '../schema'; // .js'yi ekle
import config from '../../config.js'; // tgcloud/ dışında
import { z } from 'zod'; // npm paketi yok
Her modülün ayrıca bir adı vardır — uzantısı olmadan tgcloud/ içindeki yolu, örneğin schema, lib/cart veya handlers/message. Bu ad npx tgcloud run ve CLI’nın çıktısının kullandığı addır ve bir modül bu adla da içe aktarılabilir (lib/cart‘tan, uzantı yok). Kodunuzda göreceli içe aktarmaları tercih edin. Bunlar düzenleyicinizin anladığı şeylerdir — tanıma atlama, otomatik tamamlama, yeniden adlandırma.
Çalışma zamanında neyin mevcut olduğu tam olarak iki şeydir: sdk ve alt modülleri (sdk/db, sdk/api, sdk/fetch) — tüm platform yüzeyi, bkz.
SDK
— ve kendi modülleriniz tgcloud/‘de. Tam liste bu. Kodunuz başka bir şeyi import ederse, çözülmez. Bu kısıtlama, modüllerin yüklenmesini hızlı ve çalıştırılmasını güvenli tutan şeydir.
İşleyiciler
Bir işleyici, handlers/ içindeki varsayılan dışa aktarımının platform tarafından eşleşen bir güncelleme geldiğinde çağrıldığı bir modüldür.
// handlers/message.js
import { api } from 'sdk';
export default async function (message) {
await api.sendMessage({
chat_id: message.chat.id,
text: `Dediniz ki: ${message.text ?? '(metin yok)'}`,
});
}
Bir işleyici, güncellemenin yükünü argümanı olarak alır — platform sizin için Telegram
Update
‘ini çözer. handlers/message.js,
Mesaj
(yani update.message) alır; handlers/callback_query.js,
CallbackQuery
alır; ve bunun gibi. İşleyicinin ikinci argümanı çağrı başına bir bağlam nesnesi olan ctx‘dir. Ham Update‘i ctx.update olarak taşır — yük dışındaki bir şeye ihtiyaç duyduğunuzda ona uzanın, örneğin update_id.
Bir işleyici async olabilir (genellikle öyledir) ve bir değer döndürebilir. SDK aracılığıyla Bot API’sine, veritabanına ve giden HTTP’ye erişir.
Bir işleyiciyi test etmek için gerçek bir güncellemeye ihtiyacınız yok. npx tgcloud run, bunu platformda sağladığınız yük ve mevcut yerel kodunuzla yürütür:
npx tgcloud run handlers/message '{ chat: { id: 1 }, text: "selam" }'
Argüman, işleyicinizin aldığı yükle aynı olan — JSON5 biçiminde — ctx‘nin ikinci argümanı olan yüküdür (ikinci argümanı) , --ctx ekleyin, örneğin --ctx '{ update: { update_id: 1 } }'. Bu, yerel dosyalarınıza karşı çalışır, bu nedenle dağıtım yapmadan önce değişiklikleri deneyebilirsiniz. Bkz.
run
.
Uç Noktalar
Bir uç nokta, botunuzun Mini Uygulaması tarafından çağrılan endpoints/ içindeki bir modüldür — ön ucun kendi başına yapamadığı her şey için yerdir, örneğin veritabanını okuma ve yazma, Bot API’sini çağırma veya sırlarınızla dış hizmetlerle konuşma.
// endpoints/getProfile.js
import { db, EndpointError } from 'sdk';
import { eq } from 'sdk/db';
import { profiles } from '../schema.js';
export default async function (input, ctx) {
const user = ctx.initData.user;
const profile = await db.select().from(profiles).where(eq(profiles.userId, user.id)).get();
if (!profile) throw new EndpointError('Profil bulunamadı', { userId: user.id });
return profile;
}
İlk argüman input, Mini Uygulamanın gönderdiği JSON nesnesidir. İkincisi ctx, doğrulanmış platform tarafından doğrulanmış Mini Uygulamanın
init verilerini
(user, chat, start_param, auth_date, …) taşıyan ctx.initData‘dır. İstemcinin Telegram.WebApp.initDataUnsafe ile aynı şekle sahiptir, ancak burada buna güvenebilirsiniz. Geçerli init verileri olmayan bir çağrı, kodunuz çalışmadan önce 401 ile reddedilir, bu nedenle ctx.initData.user gerçekten Mini Uygulamanızı açan kişidir. Uç noktalar yalnızca bu şekilde çağrılabilir — botunuzun Mini Uygulamasından, bir Telegram kullanıcısı tarafından — bu nedenle korunacak genel bir API yoktur ve oluşturulacak bir giriş yoktur.
Uç noktanın döndürdüğü her şey JSON olarak geri gönderilir. Bir çağrıyı reddetmek için throw new EndpointError(açıklama, parametreler?). Mini Uygulama açıklamayı ve parametreler nesnesini oldukları gibi alır. Ön uçta hata türüne göre dallanmanız gerekiyorsa, parametreler içine bir kod koyun — { code: 'STOK_DISI' }. Diğer herhangi bir istisna genel bir dahili hata olarak bildirilir ve gerçek mesaj yalnızca günlüklerinize gider, bu nedenle dahili bilgiler istemciye asla sızdırılmaz.
Bir uç noktayı Mini Uygulamadan çağırma
Mini Uygulama, resmi
Mini Uygulamalar SDK
‘dan Telegram.WebApp.Serverless.call ile bir uç noktayı ada göre çağırır, telegram-web-app.js — Mini Uygulamanızın zaten dahil ettiği betik. Init verilerini sizin için gönderir ve bir hata veya uç noktanın sonucuyla geri çağrı yapar:
Telegram.WebApp.Serverless.call('getProfile', { lang: 'en' }, function (err, profile) {
if (err) {
// err.message — açıklama; err.parameters — EndpointError'ınızın taşıdığı şeyler
if (err.type === 'ENDPOINT_ERROR') showMessage(err.message);
return;
}
render(profile);
});
Girdi isteğe bağlıdır ve düz bir nesne olmalıdır. Olmadan çağrı Serverless.call('getProfile', callback)‘tir.
err.type, uç noktanız bir EndpointError attığında 'ENDPOINT_ERROR'‘dır. Başka herhangi bir değer, platformun çağrıyı reddettiği veya uç noktanın beklenmedik bir şekilde başarısız olduğu anlamına gelir, örneğin init verileri eksik veya geçersiz olduğunda ' YETKISIZ'.
Uç nokta adları JavaScript tanımlayıcıları gibidir — harfler, rakamlar ve _, bir rakamla başlamaz (getProfile, place_order). Onları
npx tgcloud add endpoints/<name>
ile oluşturun ve Mini Uygulama olmadan kendiniz test edin
run
ile, init verilerini kendiniz ileterek:
npx tgcloud run endpoints/getProfile '{}' --ctx '{ initData: { user: { id: 1, first_name: "Ann" } } }'
Dağıtılanlar
npx tgcloud push çalıştırdığınızda, CLI schema.js, lib/, handlers/ ve endpoints/ altındaki her .js dosyasını toplar ve o tam seti projenizin modül alanı olarak gönderir — Mini Uygulamanın derleme klasörüyle birlikte, eğer tgcloud.jsonc birini adlandırıyorsa (aşağıya bakınız). Bulutta bulunan ancak projenizde bulunmayan her şey kaldırılır, bu nedenle dağıtılmış durum her zaman klasörünüzü yansıtır — silmeler dahil. tgcloud/ dışındaki hiçbir şey kod olarak dağıtılmaz — projenin geri kalanı size aittir. tgcloud/ içinde, bu konumlardan birinde olmayan bir .js dosyası (tgcloud/util.js, tgcloud/helpers/x.js) işaretlenir, böylece sessizce dağıtılmamış kalmaz. Markdown, nokta dosyaları ve .tgcloud/ asla dağıtılmaz.
Mini Uygulama ön ucu
Proje kökü size aittir ve Mini Uygulamanızın ön ucu için doğal yerdir — React, Vue, Svelte veya düz HTML ile Vite veya başka herhangi bir paketleyici tarafından oluşturulmuştur. Serverless, derleme çıktısını botunuzun yanında barındırır. Bir push, kodu ve statik dosyaları birlikte dağıtır ve uygulama https://app<app_id>.tgcloud.ai/ adresinde sunulur (push, tam adresi yazdırır — bunu Mini Uygulamanızın URL’si olarak
@BotFather
‘da kullanın).
Kötüye kullanımı bildirme. tgcloud.ai’deki Mini Uygulamalar bağımsız geliştiriciler tarafından yayınlanır. Bir
app<app_id>.tgcloud.aialt alanında yasa dışı içerik veya kötüye kullanımı bildirmek için [email protected] adresine e-posta gönderin.
Başlamak için önce ön ucu oluşturun, herhangi bir araçla, sonra üzerine Serverless ekleyin:
npm create vite@latest example_app # veya create-vue, …
cd example_app
npm create @tgcloud/bot .
Proje yaratıcısı asla dosyalarınızı üzerine yazmaz. tgcloud/ klasörünü ön ucunun yanına ekler, derleme klasörünü tanır ve botuyla birlikte dağıtan bir npm run deploy komut dosyası ekler.
Sunulan şey tgcloud.jsonc dosyasında ayarlanır, proje kökündeki proje yapılandırma dosyası:
{
"$schema": "./node_modules/@tgcloud/cli/schema/tgcloud.json",
"static": {
"source": "dist",
"spa": true,
"immutable": ["/assets/*"],
"headers": [{ "path": "/*", "set": { "Referrer-Policy": "no-referrer" } }],
"redirects": [{ "from": "/old", "to": "/new", "status": 301 }]
}
}
Yalnızca "source" gereklidir. Derleme klasörüdür, proje köküne göreli. "static" anahtarının diğerleri, nasıl sunulduğunu yapılandırır (aşağıda). init, sizin için tgcloud.jsonc oluşturur. Ön ucu tanıdığında, "source"‘u da doldurur:
| Ön uç | init, "source"‘u şuna ayarlar: |
|---|---|
| Vite — React, Vue, Svelte, Solid, … | dist |
| Next.js, Nuxt, SvelteKit, React Router, TanStack Start, Angular | hiçbir şey — önce statik bir dışa aktarma yapılandırın, sonra "source"‘u onun klasörüne ayarlayın |
Başka herhangi bir kurulumla, "source"‘u derleme klasörünüze kendiniz ayarlayın.
$schema satırı, düzenleyiciniz için her anahtar için otomatik tamamlama ve doğrulama sağlar. Dosya, yorumları olan ve son virgüllere izin veren JSON’dur. Başka bir aracınızın onu düz JSON olarak okuması gerekirse, bunun yerine tgcloud.json olarak adlandırın — o zaman katı JSON olmalıdır.
İtmden önce derleyin. push, klasörü diskteki tam haliyle yükler — bir nokta ile başlayan dosya ve klasörler hariç, bunlar atlanır — ve asla derlemenizi çalıştırmaz, bu nedenle ön uçta düzenleme yaptıktan sonra düz bir npx tgcloud push önceki derlemeyi dağıtırdı. npm run deploy kullanın (yapı betiğinizi çalıştırır, sonra tgcloud push) veya önce kendiniz derleyin.
Sunma seçenekleri şunlardır:
spa— var olmayan ve dosya uzantısı olmayan yollar içinindex.htmlsunar, böylece istemci tarafı bir yönlendirici yeniden yüklemede çalışır. Uzantısı olan yollar hala404alır.immutable— tarayıcıların bir yıl boyunca önbelleğe alabileceği içerik hash’li dosyalar (Vite’nin/assets/*) için desenler. Yalnızca içerik hash’li dosyalar için kullanın. Burada eşleşen başka bir dosya, tarayıcılarda bir yıl boyunca güncelliğini yitirecek ve geri çağırmanın bir yolu olmayacaktır.headers— bir kuralın eşleştiği yollar (tam bir yol veya/*ile biten bir önek) için yanıt başlıkları.nulldeğeri bir başlığı kaldırır.redirects— yönlendirme kuralları, ilk eşleşme kazanır. Mevcut bir dosya her zaman bir kuralı yener.status, ayarlamazsanız301‘dir."static": "dist"— başka hiçbir şeye ihtiyacınız olmadığında{ "source": "dist" }için bir kısayol."static": false— bir sonraki itmede dağıtılmış siteyi kaldırın. Bunun yerine anahtarı silmek, bu projenin statik dosyaları yönetmesini durdurur ve dağıtılan her şey kalır.
Site, kendi ana bilgisayarının kökünden sunulur, bu nedenle paketleyicinizin varsayılan base (/) doğrudur. Telegram Web, Mini Uygulamaları bir iframe içinde açar, bu nedenle X-Frame-Options veya kısıtlayıcı bir frame-ancestors ilkesi eklemeyin.
Aynı ana bilgisayar, uç noktalarınızı /api/ altında yanıtlar — Telegram.WebApp.Serverless.call('getProfile', …) buraya gider. Derleme klasörünüzde /api/ altına kendi dosyalarınızı koymayın.
Veritabanı
Her bota kendi veritabanı — çağrılar arasında kalıcı olan ve her modül tarafından db aracılığıyla erişilebilen bir SQLite destekli depolama — verilir. Tablolarınızı küçük, yazılmış bir DSL ile schema.js‘de açıklarsınız; akıcı bir sorgu oluşturucu ile okursunuz ve yazarsınız; ve gözden geçirilmiş geçişlerle geliştirirsiniz.
Drizzle ORM biliyor musunuz? O zaman veritabanıyla burada nasıl konuşacağınızı zaten biliyorsunuz. Şema DSL’si ve sorgu oluşturucusu, sütun oluşturucuları,
select().from().where(), operatörleri,onConflictDoUpdate,.returning()vesqletiketinin hepsinin beklediğiniz gibi davrandığı Drizzle’ı takip eder, bu nedenle veri okumak ve yazmak zaten kullandığınız tanıdık API’dir. Sadecesdk/db‘den içe aktarırsınız ve platformun birkaç özelliği (en önemlisi yabancı anahtar yok ) ortaya çıktığı yerlerde belirtilir.
Tablo bildirme
Tablolar, schema.js‘de adlandırılmış dışa aktarımlardır. table()‘ı çağırmak, yükleme zamanında bir açıklama oluşturur (veritabanına dokunmaz); platform, schema.js‘yi dağıttığınızda dışa aktarılan tabloları keşfeder ve veritabanını bunlara uyacak şekilde geçirir.
import { table, integer, text, boolean, json, index, sql } from 'sdk/db';
export const users = table('users', {
id: integer('id').primaryKey({ autoIncrement: true }) ,
tgId: integer('tg_id').unique() ,
name: text('name').notNull() ,
lang: text('lang').default('en') ,
isAdmin: boolean('is_admin').default(false) ,
prefs: json('prefs') ,
created: integer('created_at', { mode: 'timestamp' }).default(sql`(unixepoch())`) ,
}, (t) => ({
createdIdx: index('idx_users_created').on(t.created) ,
}));
table(ad, sütunlar, ekstralar?):
adSQL tablo adıdır;sütunlarJS özelliği → sütun tanımı eşleşmesidir;ekstralaristeğe bağlı bir geri arama fonksiyonudur(t) => ({ … })buradatsütunları gösterir (t.createdo sütuna bir referanstır) — burada dizinler ve tablo düzeyinde kısıtlamalar bildirin.
Sütun türleri
| Fabrika | SQLite türü | Notlar |
|---|---|---|
text() |
TEXT | |
integer() |
INTEGER | |
real() |
REAL | takma adı float() |
numeric() |
NUMERIC | |
blob() |
BLOB | Uint8Array okur/yazar |
boolean() |
INTEGER | 0/1 olarak saklanır, true/false olarak okunur |
json() |
TEXT | otomatik JSON.stringify / JSON.parse |
Sütun adı argümanı isteğe bağlıdır — atlayın ve JS anahtarı kullanılır.
modeseçeneği, değerlerin SQLite ve JavaScript arasında nasıl dönüştüğünü kontrol eder.
mode |
Şöyle saklanır | JS değeri |
|---|---|---|
boolean |
INTEGER 0/1 | boolean |
json |
TEXT (JSON) | herhangi bir nesne/dizi |
timestamp |
INTEGER (unix saniye) | Date |
timestamp_ms |
INTEGER (unix ms) | Date |
bytes |
BLOB | Uint8Array |
boolean() ve json() integer(ad, { mode: 'boolean' }) ve text(ad, { mode: 'json' }) için kısayollardır.
blob() bir Uint8Array okur ve yazar — çalışma zamanında Node Buffer yoktur (ve Buffer, Uint8Array alt sınıfıdır, bu nedenle bu taşınabilir temel türdür). Yukarıdaki mode, sütunun depolama türünden bağımsız olarak yalnızca değerin nasıl kodlandığını yönetir: bu nedenle blob('col', { mode: 'json' }), bir BLOB sütununda tutulan json()‘ın BLOB eşdeğeridir, TEXT yerine.
ÖZET:
blob()Uint8Arraykullanır.mode, depolama değil kodlamayı yönetir, bu nedenleblob(..., { mode: 'json' })JSON’u BLOB olarak saklar,json()ise TEXT olarak saklar.
Sütun değiştiricileri
Sütun değiştiricileri bir sütuna zincirlenir.
integer('id').primaryKey({ autoIncrement: true })
text('name').notNull()
text('tg').unique()
text('lang').default('en')
integer('created_at', { mode: 'timestamp' }).default(sql`(unixepoch())`)
text('slug').generatedAlwaysAs(sql`lower(name)`, { mode: 'stored' }) // veya 'virtual'
text('email').deprecated('replaced by login') // sütunu kaldırma için işaretler
Bir
json()sütunundaki.default()değeri sizin için kodlar; birsql`…`varsayılanı olduğu gibi geçirilir..deprecated()sonludur — bkz. Geçişler .
Diziler ve kısıtlamalar
Diziler ve kısıtlamalar ekstralar geri çağırmasında bildirilir, burada sütunlar kapsamdadır.
table('t', { /* … */ }, (t) => ({
uq: unique('uq_email').on(t.email) ,
chk: check('chk_done', sql`${t.done} in (0, 1)`) ,
idx: index('idx_name').on(t.col) ,
uidx: uniqueIndex('uidx_email').on(t.email) ,
lower: index('idx_lower').on(sql`lower(${t.email})`) , // ifade dizini
active: index('idx_active').on(t.userId).where(sql`done = 0`) , // kısmi dizin
}));
Tablo düzeyinde değiştiriciler table(...)‘dan sonra zincirlenir: .strict(), .withoutRowid(), .deprecated('reason').
Yabancı anahtar yok
Çalışma zamanı PRAGMA foreign_keys kapalı olarak çalışır. Bildirilen bir yabancı anahtar sessizce etkisiz olur — geçişler, yetim koruması yok — bu hiç olmamasından daha kötüdür, bu nedenle DSL bunu imkansız kılar. Adı, .references() ve tablo düzeyinde foreignKey() bildirildiğinde atar ve kullanan bir şema dağıtılmaz.
İlişkileri düz sütunlarla (userId: integer('user_id')) modellemeli ve bütünlüğü uygulama kodunuzda zorlamalısınız: anaları çocuklardan önce ekleyin, çocukları anelerden önce silin, hataları düzgün bir şekilde işleyin ve ihtiyacınız olduğunda LEFT JOIN … WHERE parent.id IS NULL ile yetimleri temizleyin.
Yabancı anahtarların olmaması kasıtlı bir kısıtlamadır, gözden kaçırma değildir. Botunuzu planlarken bunu erken hesaba katın.
Sorgulama
db, akıcı bir sorgu oluşturucudur. Her sorgu asenkrondur — terminal yöntemleri (.all(), .get(), .values(), .run()) Promise döndürür, bu nedenle her zaman await yapın.
import { db } from 'sdk';
import { eq, and, desc, asc, count, sql } from 'sdk/db';
import { users, todos } from '../schema.js';
await db.select().from(todos).all(); // tüm satırlar
await db.select().from(todos).where(eq(todos.id, 1)).get(); // ilk satır veya null
await db.select().from(todos).values(); // değer dizileri olarak satırlar
await db.select().from(todos)
.where(and(eq(todos.userId, uid) , eq(todos.done, false)))
.orderBy(desc(todos.priority) , asc(todos.id))
.limit(10).offset(20)
.all();
// özel projeksiyon: { takma ad: sütunRef | sqlExpr | toplama }
await db.select({ id: todos.id, title: todos.text, n: count() })
.from(todos).groupBy(todos.userId).having(sql`count(*) > ${1}`).all();
// satır sayısı — bir yardımcı, oluşturucu terminali değil:
await db.$count(todos); // tüm satırlar
await db.$count(todos, eq(todos.done, false)); // bir filtre ile
- Zincirlenebilir:
.where(),.orderBy(),.limit(),.offset(),.groupBy(),.having(),.distinct(). - Terminaller:
.all(),.get(),.values(). - Satırları
db.$count(tablo, where?)(veya projeksiyondacount()) ile sayın.
Ekle, güncelle, sil:
await db.insert(todos).values({ userId: 1, text: 'Süt al' }).run();
await db.insert(todos).values([{ text: 'A' }, { text: 'B' }]).run(); // toplu işlem
await db.insert(todos).values({ text: 'X' }).returning().run(); // RETURNING *
await db.insert(users).values({ tgId: 42, name: 'Ann' })
.onConflictDoUpdate({ target: users.tgId, set: { name: 'Ann' } }).run();
await db.update(todos).set({ done: true }).where(eq(todos.id, 1)).run();
await db.delete(todos).where(eq(todos.id, 1)).run();
Bir toplu eklemenin tek bir deyim olduğunu unutmayın, bu nedenle SQLite’ın değişken sınırı (satırlar × sütunlar) tarafından sınırlandırılır; üzerine çıkarsanız, ekleme hatalarla sonuçlanır — kendiniz parçalayın.
Operatörler sdk/db‘den içe aktarılır:
import {
eq, ne, gt, gte, lt, lte,
like, notLike,
isNull, isNotNull, and, or, not,
between, notBetween, inArray, notInArray,
count, sum, avg, min, max,
asc, desc,
} from 'sdk/db';
Birden fazla argümanla .where(a, b), and(a, b) ile aynıdır. Bir karşılaştırmanın ikinci argümanı varsayılan olarak bir değerdir, ancak başka bir sütun veya sql`…` olabilir — örn. eq(a.x, b.y). Toplamalar (count/sum/avg/min/max), bir .select({ … }) projeksiyonu için SQL parçalarıdır.
Ham SQL — oluşturucu yeterli olmadığında, ham SQL’e düşürün. Mod, yöntemle seçilir: yazmalar için db.run, çok satır için db.all, tek satır için db.get, konumsal diziler olarak satırlar için db.values.
await db.run('UPDATE todos SET done = 1 WHERE id = :id', { ':id': 5 });
// → { rowsAffected: 3, lastInsertRowid: 0, rows: [] }
await db.all(sql`SELECT * FROM todos WHERE done = ${false}`);
await db.get(sql`SELECT count(*) AS c FROM todos`);
await db.values(sql`SELECT id, text FROM todos`); // → [[1, 'buy milk']]
Bir yazma, bir çalıştırma sonucu’na çözülür — rowsAffected, lastInsertRowid ve RETURNING yan tümcesi varsa rows. Bir sorgu iki sütunu aynı adla (birleştirme gibi SELECT u.id, o.id) yansıttığında db.values‘e uzanın: db.all satırları sütun adına göre anahtarlar, bu nedenle ikinci id ilkini üzerine yazardı.
sql`…` etiketi ${value}‘yu bağlı bir parametreye ve ${table.column}‘ı bir tanımlayıcıya dönüştürür ve iç içe sql parçalarını birleştirir. Parametre olmadan değişmez bir dize için sql.raw('…') kullanın.
Ham sorgular bir tabloya bağlı değildir, bu nedenle satırları mod dönüşümü olmadan geri gelir — bir boolean
0/1, bir JSON sütunu bir dizedir, bir zaman damgası bir sayıdır. Yalnızca tabloya bağlı oluşturucu değerleri dönüştürür.
Geçişler
Botunuz büyüdükçe veritabanınız değişir. Platform bunu, kod dağıtımını veri değiştirme işleminden ayırarak ve her şema değişikliğini ne kadar riskli olduğuna göre sınıflandırarak güvence altına alır.
Dağıtım asla veritabanına dokunmaz. Değiştirilmiş bir schema.js‘yi npx tgcloud push yaptığınızda, platform yeni şemayı kaydeder ve veritabanının ne değişeceğini size söyler — ancak hiçbir şeyi uygulamaz:
npx tgcloud push # schema.js'yi dağıtır; bekleyen DB değişikliklerini bildirir
npx tgcloud migrate # gözden geçir ve uygula
npx tgcloud migrate, şemanız ile canlı veritabanı arasındaki farkı hesaplar, sonra sizi adım adım adım bir [N/M] sayacıyla gezer:
- Tüm bekleyen değişikliklerin kısa bir özeti.
- Onayınız üzerine tek bir adımda uygulanan güvenli değişiklikler.
- Her biri ayrı ayrı onaylanan uyarılar (silmeler, yavaş işlemler).
- Kılavuzla gösterilen manuel değişiklikler, otomatik olarak uygulanmaz.
- Farkındalık için gösterilen belgelenmemiş nesneler (veritabanında ancak şemanızda değil).
Güvenli değişiklikler hızlı ve tersine çevrilebilirdir, bu nedenle birlikte geçerler. Her uyarı kasıtlı, bireysel bir onaydır — yıkıcı değişiklikler için “hepsini uygula” seçeneği yoktur.
Komutların bayrakları (
--dry-run,--safe,--yes,--local) içinmigratebölümüne bakın.
Bir şeyleri kaldırma
Bir tabloyu veya sütunu schema.js‘den silmek, onu düşürmez — kazara silinmesi felaket olurdu. Bir şeyi kaldırmak için onu modası geçmiş olarak işaretleyin:
// bir sütunu düşür
text('email').deprecated('replaced by login')
// tüm tabloyu düşür
export const oldSessions = table('old_sessions', { /* … */ }).deprecated('unused');
Bir sonraki migrate üzerinde, modası geçmiş nesne bireysel olarak onayladığınız uyarı durumu düşüşü olarak görünür. Bir kez kaybolduğunda, bildirimi kaldırın.
Bir sütunun türünü değiştirme
Tür değişiklikleri manueldir — SQLite bunları her zaman yerinde yapamaz ve mevcut değerleri zorlamak bir yargı kararıdır. migrate, değişikliği ve nedenini gösterecektir; yeni bir sütun veya tablo oluşturarak, verileri kopyalayarak ve değiştirerek bunu kendiniz yapın (db.run(...) ile).
SDK
Çalışma zamanında bir modülün tek bir kitaplığı vardır: sdk. Bir bot arka ucunun ihtiyaç duyduğu üç şeyi — bir veritabanı, Telegram Bot API’si ve giden HTTP — kuracak bir şey olmadan ve yapılandıracak kimlik bilgisi olmadan paketler. Veritabanı (db),
Veritabanı
bölümünde ele alınmıştır; bu bölüm api, fetch ve console küresel değişkenini kapsar.
import { db, api, fetch, InputFile, BotApiError, EndpointError } from 'sdk'; // tüm yüzey
// alt modüllerden:
import { table, integer, text, eq, sql } from 'sdk/db';
import { api } from 'sdk/api';
import { fetch } from 'sdk/fetch';
| İçe Aktarma | Nedir |
|---|---|
db |
Veritabanı — sorgu oluşturucu ve şema DSL → Veritabanı |
api |
Telegram Bot API — api.sendMessage(...) →
aşağıda
|
fetch |
Giden HTTP → aşağıda |
InputFile |
Yüklenecek bir dosya (bayt + ad) — hem api hem de fetch ile çalışır →
Dosyalar
|
EndpointError |
Mini Uygulamanın bir mesajla reddetmesi → Uç Noktalar |
Kendi proje modüllerinizi .js uzantılı göreceli yol ile içe aktarın (../schema.js‘den, ../lib/cart.js‘den). Bkz.
Modül Sistemi
.
Bot API’si
api, size tüm
Telegram Bot API’sini
sağlar. Herhangi bir yöntemi api.<method>(parametreler) olarak çağırın. Her mevcut — ve gelecekteki — Bot API yöntemi, SDK güncellemesi gerekmeden çalışır.
import { api } from 'sdk';
const me = await api.getMe(); // → çözülmüş sonuç
await api.sendMessage({ chat_id: id, text: 'Merhaba!' });
await api.editMessageText({ chat_id, message_id, text: 'Güncellendi' });
await api.answerCallbackQuery({ callback_query_id, text: 'Bitti' });
Yanıt zarfı çözülmüştür. Bot API normalde sonuçları { ok: true, result: … } içine sarar. api, result‘ı doğrudan döndürür — getMe() kullanıcı nesnesine çözülür, bir sarmalayıcıya değil. Parametreler, Bot API’nin kendi yılan_alt çizgi adlarını kullanır (chat_id, message_id, reply_markup, …).
Hatalar BotApiError atar. Bot API { ok: false } döndürdüğünde, çağrı yanlış bir değer döndürmek yerine bir BotApiError atar, bu nedenle onu yanlışlıkla göz ardı edemezsiniz. Hata .code (Bot API error_code), .description (insan tarafından okunabilir mesaj) , .method (hangi yöntem başarısız oldu) ve .parameters (429’daki retry_after gibi ek veriler veya migrate_to_chat_id) taşır. Beklenen bir hatayı işlemek için onu yakalayın ve geri kalanları yeniden atın:
import { api, BotApiError } from 'sdk';
try {
await api.deleteMessage({ chat_id, message_id });
} catch (e) {
if (e instanceof BotApiError && e.code === 400) {
// 400 = mesaj zaten gitti; burada sorun değil.
} else {
throw e;
}
}
Dosyalar
Yalnızca file_id‘lerle değil, dosya baytlarıyla çalışın — yeni dosyalar yükleyin ve mevcut olanları indirin.
Yükle — InputFile. Ham baytları bir InputFile‘a (bayt, dosya adı ve isteğe bağlı bir MIME type içeren düz bir tutucu) sarın ve bir dosya bekleyen herhangi bir Bot API yöntemine geçirin:
import { api, InputFile } from 'sdk';
const doc = new InputFile(bytes, 'rapor.pdf', { type: 'application/pdf' });
await api.sendDocument({ chat_id, document: doc });
// parametreler içine yerleştirilmiş dosyalar da çalışır — örn. bir albüm:
await api.sendMediaGroup({ chat_id, media: [
{ type: 'photo', media: new InputFile(a, 'a.jpg', { type: 'image/jpeg' }) },
{ type: 'photo', media: new InputFile(b, 'b.jpg', { type: 'image/jpeg' }) },
]});
Baytlar, platforma tek bir çağrıda tüm dosyanın belleğe alınmasıyla değil, çok parçalı bir yük olarak Telegram’a akıtılır — ancak Telegram’ın Bot API sınırlamaları hala geçerlidir: bir bot şu anda dosya başına en fazla 50 MB (ve fotoğraf için 10 MB) yükleyebilir.
İndir — file_id ile. İki yardımcı bir dosyanın baytlarını geri çeker. Platform file_id‘yi sizin için çözer (arka planda getFile‘ı çalıştırır ve içeriği alır), bu nedenle bot jetonuna veya bir indirme URL’sine asla dokunmazsınız:
const bytes = await api.getFileContent(file_id); // → Uint8Array (tüm dosya)
const { file, body } = await api.getFileStream(file_id); // bunun yerine akıtın
file.file_unique_id; // getFile bilgisi
for await (const chunk of body) { /* Uint8Array */ } // veya tamponlayın: await stream.bytes()
Telegram’ın Bot API’si
getFileindirmelerini 20 MB ile sınırlar, bu nedenle her iki yardımcı için de sınır budur.
HTTP
fetch, dış dünyayı — üçüncü taraf API’leri, webhook’ları, HTTP üzerinden her şeyi — çağırmak için fetch benzeri bir istemcidir.
import { fetch } from 'sdk';
const res = await fetch('https://api.example.com/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Pavel' }) ,
});
if (!res.ok) throw new Error(res.statusText);
const data = await res.json();
Yanıt web platformunu yansıtır: res.status, res.statusText, res.ok (200-299 için doğru), res.url, res.headers (.get(), .has(), .keys(), .entries()) ve gövde okuyucuları await res.json() / await res.text().
Gövdeyi bir akış olarak artımlı olarak da okuyabilirsiniz —
for await (const chunk of res.body) { … }— bu, sunucu tarafından gönderilen olayları veya yapay zeka API’lerinden jeton bazında çıktıyı tüketmenin yoludur.
Gövde yardımcıları eşleşen Content-Type‘ı sizin için ayarlar:
await fetch(url, { method: 'POST', body: fetch.body.json({ a: 1 }) }); // application/json
await fetch(url, { method: 'POST', body: fetch.body.form({ a: 1 }) }); // x-www-form-urlencoded
await fetch(url, { method: 'POST', body: fetch.body.text('selam') }); // text/plain
İstek gövdeleri ayrıca dosyalar ve ham baytlar taşıyabilir: Uint8Array, InputFile veya FormData ( multipart/form-data için) gövde olarak geçirin ve baytlar akıtılır — böylece üçüncü taraf bir API’ye, dosyaları Telegram’a gönderdiğiniz gibi yükleyebilirsiniz:
import { fetch, FormData, InputFile } from 'sdk';
const form = new FormData();
form.append('file', new InputFile(bytes, 'photo.jpg', { type: 'image/jpeg' }));
form.append('caption', 'botumdan');
const res = await fetch('https://api.example.com/upload', { method: 'POST', body: form });
Aksi takdirde standart fetch gibi davranır, iki kısıtlama ile:
- Yanıt, metin olarak okunur —
await res.json()/await res.text(), veyares.bodyile akıtılır. - Toplam yanıt 30 MB ile sınırlıdır. Bu sınır, tüm yanıtı kapsar —
res.bodyile akıtmak, büyük bir gövdeyi artımlı olarak işlemenize olanak tanır, ancak sınırı yükseltmez.
Günlük Kaydı
Standart küresel console mevcuttur — içe aktarılacak bir şey yok, herhangi bir JavaScript’te olduğu gibi oradadır. Çıktısı yakalanır ve npx tgcloud run tarafından gösterilir, bu da onu geliştirme sırasında birincil hata ayıklama aracınız yapar.
console.log('işleniyor', { chatId: id }); // günlük / hata ayıklama — düz
console.info('başladı'); // bilgi — mavi
console.warn('oran sınırlı'); // uyarı — sarı
console.error(err); // hata — kırmızı, yığın iziyle
Her satır geldiği [dosya:satır] ile etiketlenir. console.error ve console.trace tam bir yığın eklerken, console.warn eklemez. Bir modülü npx tgcloud run ile çalıştırdığınızda, bu satırlar seviye başına renkli bir önek, çalıştırmanın başladığından bu yana geçen süre ve kaynak ile yazdırılır — bkz.
run
.
Komut satırı arayüzü
tgcloud, projenizin klasörü ile bulut arasındaki köprüdür. Projeleri oluşturur, size neyin değiştiğini gösterir, dağıtır, modülleri çalıştırır ve veritabanı geçişlerini uygular.
Node.js
18 veya daha yenisini gerektirir. İki şekilde elde edebilirsiniz:
# Önerilen — içine yüklenmiş CLI ile bir proje oluşturun:
npm create @tgcloud/bot example_bot
# Veya CLI'yı küresel olarak yükleyin ve boş bir klasörü başlatın:
npm install -g @tgcloud/cli
tgcloud init
npm paketi @tgcloud/cli‘dır ve kurduğu komut tgcloud‘dur. Her komut projenizin herhangi bir alt klasöründen çalışır.
| Komut | Amaç |
|---|---|
init
|
Mevcut klasörde yeni bir proje oluşturur |
add
|
Yeni bir modül (işleyici, uç nokta veya lib modülü) oluşturur |
login
|
Projeyi bir bota bağlar (jetonu kaydeder) |
status
|
Yerel olarak neyin değiştiğini bulut ile gösterir |
diff
|
Satır satır değişiklikleri gösterir |
push
|
Değiştirilmiş modülleri ve Mini Uygulamanın derlemesini buluta dağıtır |
migrate
|
Veritabanına şema değişikliklerini uygular |
run
|
Dağıtım yapmadan modülü platformda yürütür |
fetch
|
Dağıtılmış olanı, yerel dosyaları değiştirmeden kontrol eder |
pull
|
Yerel dosyaları buluta uyumlu hale getirir |
reset
|
Yerel değişiklikleri atar; bulut durumundan geri yükler |
webhook
|
Platform tarafından yönetilen webhook’u denetler ve yeniden senkronize eder |
completion
|
Bir kabuk tamamlama komut dosyası yazdırır (bash/zsh/fish) |
upgrade
|
0.2.0 öncesi bir proje düzenini tgcloud/ içine taşır |
Kimlik Doğrulama
Bir proje, app<id>:<secret> biçimindeki jetonuna göre tek bir bota bağlanır. app<id> kısmı halka açıktır ve yazdırılabilir; gizli kısım asla günlüklerde veya hatalarda görünmez.
Jeton şu sırayla çözülür:
TGCLOUD_TOKENortam değişkeni — CI için; asla diske yazılmaz..tgcloud/credentials—npx tgcloud logintarafından yazılır.- Hiçbiri değilse → sizi
npx tgcloud login‘a yönlendiren bir hata.
CLI, komut sırasında asla bir jeton istemez. Giriş yapmak her zaman açık login adımıdır. Kayıtlı bir jeton geçersiz hale gelirse, CLI onu kaldırır ve tekrar login yapmanızı ister.
init
npx tgcloud init
Mevcut dizinde yeni bir proje oluşturur: tgcloud/ klasörü schema.js, lib/, handlers/ ve bir başlangıç işleyicisi ile birlikte tgcloud.jsonc, AGENTS.md, docs/ ve .tgcloud/ durum klasörü. Mevcut bir ön uç projesinin kökünde de çalıştırın — tgcloud/ klasörünü ve belgeleri ekler ve asla dosyalarınızı üzerine yazmaz. Ön ucu tanırsa, ayrıca tgcloud.jsonc‘yi derleme klasörüne yönlendirir ve package.json‘a bir deploy komut dosyası ekler (derle, sonra it) — yalnızca zaten bir deploy komut dosyanız yoksa. Bkz.
Mini Uygulama ön ucu
.
init, bir projenin başka bir proje içine oluşturulmasını reddeder. Bir projenin kendi kökünde tekrar çalıştırılması sorun değil ve yalnızca eksik olanı ekler.
add
npx tgcloud add <hedef>
Tek bir yeni modül, kablolu ve düzenlemeye hazır — bir işleyici, bir uç nokta veya bir lib/ modülü oluşturur.
npx tgcloud add handlers/callback_query # yeni bir güncelleme işleyicisi
npx tgcloud add endpoints/getProfile # Mini Uygulama için yeni bir uç nokta
npx tgcloud add lib/cart # yeni bir paylaşılan modül
Not:
addasla mevcut bir dosyayı üzerine yazmaz.
<hedef>, modülün yoludur (son .js isteğe bağlıdır). handlers/ için ad, bir Telegram güncelleme türü olmalıdır. Platform geçerli kümeyi duyurur, bu nedenle geçersiz bir ad hemen reddedilir. handlers/ ve endpoints/ düzdür, oysa lib/ iç içe olabilir (lib/payments/stripe).
Modül adı gereklidir. Yalnızca dizini vermek bir hatadır — ancak yardımcı bir hata: handlers/ için, sahip olmadığınız güncelleme türlerini listeler, böylece birini kopyalayabilirsiniz.
$ npx tgcloud add handlers
Error: Belirli bir ad belirtin, örn. "handlers/callback_query". Mevcut handlers/ türler: callback_query, inline_query, chat_member, …
<Sekme>tamamlama aynı kümeyi sunar — bkz.completion.
Oluşturulan dosya canlı bir export default içerir, bu nedenle işleyici dağıtılır dağıtılmaz aktiftir — yorumunu kaldırmak için bir şey yok. Yeni modülü
push
ile dağıtın.
login
npx tgcloud login
CLI erişim jetonunuzu ister —
@BotFather
→ botunuz → Serverless → CLI Access → Access token’dan, botunuzun
API jetonundan
ayrı bir jeton — platforma karşı doğrular ve .tgcloud/credentials‘a kaydeder.
login, jeton isteyen tek komuttur ve etkileşimli bir terminal gerektirir. CI’da bunun yerineTGCLOUD_TOKENayarlayın.
status
npx tgcloud status
Dosya başına, çalışma diziniz ile dağıtılmış kopya arasındaki neyin değiştiğini gösterir: değiştirilmiş, yeni, silinmiş, değişmemiş. Çevrimdışı çalışır, son push, pull veya fetch‘in bulut durumuyla karşılaştırır. Ayrıca tgcloud/ içindeki dağıtılmayacak dosyalar hakkında da uyarır.
Mini Uygulamalı bir proje için status, son dağıtımdan bu yana derleme klasöründeki değişiklikleri de gösterir.
diff
npx tgcloud diff
status gibi, ancak değiştirilmiş modüller için satır satır gerçek farkları gösterir. Çevrimdışı da.
push
npx tgcloud push [dosyalar...]
Projenizi tek bir atomik toplu işlemde buluta dağıtır.
Argümansız olduğunda, tüm projeyi dağıtır ve dağıtılmış durum klasörünüzü tam olarak yansıtacak şekilde ayarlanır — yerel olarak sildiğiniz modüller bulutta kaldırılır.
Dosya veya dizin argümanlarıyla (npx tgcloud push tgcloud/handlers/message.js, npx tgcloud push handlers/) , yalnızca bu dosyalardaki değişiklikleri dağıtır. Hedeflenen bir itme diğer modülleri asla silmez. Bir hedef, dosya yolu (tgcloud/handlers/message.js), tgcloud/ içindeki yol (handlers/message.js) veya modül adı (handlers/message) olarak yazılabilir — hepsi aynı modülü ifade eder.
Seçeneği --force — eşzamanlılık denetimini atlamak ve buluttaki her şeyi üzerine yazmak. Yalnızca emin olduğunuzda kullanın (bkz.
Senkronize Kalma
).
tgcloud.jsonc bir statik klasör adlandırıyorsa, tam bir push onu aynı toplu işlemde dağıtır — yalnızca değişen dosyalar yüklenir — ve sitenin adresini yazdırır. Önce derleyin, çünkü push asla derlemenizi çalıştırmaz (npm run deploy her ikisini de yapar). npx tgcloud push dist/ yalnızca statik dosyaları dağıtır ve yalnızca modülleri adlandıran bir itme onları dokunulmaz bırakır.
Bir dağıtımdan sonra, schema.js değiştiyse ve veritabanı senkronize değilse, push bekleyen değişikliklerin bir özetini yazdırır ve npx tgcloud migrate önerir. Asla onları otomatik olarak uygulamaz.
migrate
npx tgcloud migrate
Şema değişikliklerinizi veritabanına uygular. schema.js ile canlı veritabanı arasındaki farkı hesaplar, sonra sizi adım adım bir adımda bir adımda bir [N/M] sayacıyla gezer:
- Bekleyen tüm değişikliklerin kısa bir özeti.
- Onayınız üzerine tek bir adımda uygulanan güvenli değişiklikler.
- Her biri ayrı ayrı onaylanan uyarılar (silmeler, yavaş işlemler).
- Kılavuzla gösterilen manuel değişiklikler, otomatik olarak uygulanmaz.
- Farkındalık için gösterilen belgelenmemiş nesneler (veritabanında ancak şemanızda değil).
Sonunda bir özetle biter: uygulanan, atlanan, manuel düzeltme bekleyen veya şemada olmayan.
Model için bkz. Geçişler .
Seçenekler: --dry-run (her şeyi yazdır, hiçbir şeyi uygulama), --safe (güvenli değişiklikleri otomatik uygula, uyarıları atla), --yes (güvenli değişiklikleri ve her uyarıyı otomatik uygula, manuel olanı atla — dikkatli kullanın), --local (yerel schema.js‘ye karşı dağıtılmış olan yerine fark alır). Bayrak olmadan, migrate bir terminal gerektirir ve tahmin etmek yerine etkileşimli olmayan bir ortamda hata verir.
run
npx tgcloud run <modül> [argümanlar] [--ctx <json5>]
Bir işleyiciyi veya uç noktayı dağıtım yapmadan platformda yerel mevcut dosyalarınızı kullanarak yürütür. Bu, mantığı test etmek için hızlı iç döngüdür.
<modül>— çıplak bir ad (handlers/veendpoints/altında aranır) veyahandlers/messagegibi bir yol. Her iki dizinde de bulunan çıplak bir ad, diziniyle yazılmalıdır.[argümanlar]— işleyiciye geçirilen yük, JSON5 biçiminde yazılmış, bu nedenle anahtarları alıntılamayı atlayabilirsiniz. İşleyicinizin aldığı güncelleme türü nesnesidir (örneğinhandlers/messageiçin bir Mesaj) veya bir uç noktanıninput‘udur ve bir nesne olmalıdır — bir dizi veya çıplak bir dize değil.--ctx <json5>— modülün bağlam nesnesi (ikinci argümanı), yine JSON5. Kullandığınız şeyleri sağlamak için kullanın — bir işleyici için ham güncelleme,--ctx '{ update: { update_id: 1 } }', veya bir uç nokta için init verileri,--ctx '{ initData: { user: { id: 1 } } }'.run, test ettiğiniz mantık olduğu için platformun kontrollerini doğrulamaz.
npx tgcloud run handlers/message '{ chat: { id: 1 }, text: "selam" }'
Platform, modülü yerel projenizden derlenen modül alanı ve (bu nedenle yerel olarak değiştirilmiş lib/ kodu da kullanılır) üzerinde çalıştırır ve geri dönen değeri, console.* ile günlüğe kaydedilen her şeyi ve geçen süreyi döndürür. Büyük argümanları bir dosyadan npx tgcloud run handlers/message "$(cat message.json5)" ile okuyun.
fetch
npx tgcloud fetch
Çalışan dosyalarınızı etkilemeden şu anda dağıtılmış olanları kontrol eder. Sonrasında, status ve diff en son bulut durumuyla karşılaştırır. Bir çatışmayı çözme kararı vermeden önce bakmak için kullanışlıdır.
pull
npx tgcloud pull
Çalışan dosyalarınızı dağıtılmış duruma getirerek yerel projenizi buluta uyumlu hale getirir.
pull asla Mini Uygulamanızın derleme klasörünü yazmaz.
reset
npx tgcloud reset
Yerel değişikliklerinizi atar ve modülleri son bilinen bulut durumundan geri yükler. Bir deneyi atmak için kullanın. Mini Uygulama derleme klasörü dokunulmaz.
webhook
npx tgcloud webhook
npx tgcloud webhook sync [--drop-pending]
Telegram, güncellemeleri botunuza sizin için yönettiği bir webhook aracılığıyla iletir — asla elle bir yere işaret etmezsiniz. npx tgcloud webhook, mevcut durumunu gösterir: URL, allowed_updates listesi, bekleyen güncelleme sayısı, son teslim hatası (varsa) ve dağıtılmış işleyicilerinizle senkronize olup olmadığı.
“Senkronize” demek, webhook’un platformu işaret ettiği ve allowed_updates‘ının dağıtılmış işleyicilerinizle eşleştiği anlamına gelir — böylece Telegram yalnızca işlediğiniz güncelleme türlerini ve başka hiçbir şeyi teslim eder. Yeni bir işleyici dağıtmak (veya birini kaldırmak) senkronizasyonun dışında bir webhook bırakabilir, yeniden senkronize edilene kadar; npx tgcloud status da bunu işaretler.
npx tgcloud webhook sync bunu düzeltir — webhook’u platforma geri işaretler ve dağıtılmış işleyicilerinizden allowed_updates‘ı yeniden oluşturur. Eşitleme tamamlandıktan sonra webhook sağlıklı olduğunda Telegram’ın zaten kuyruğa aldığı güncellemeleri atmak için --drop-pending ekleyin (aksi takdirde teslim edilirler).
completion
Not: Sekme tamamlama yalnızca çıplak
tgcloudPATH‘inizde olduğunda çalışır — bu nedenle onu küresel olarak yükleyin (npm install -g @tgcloud/cli) veya başka bir şekilde ikiliyiPATH‘inize yerleştirin.npxile kanca yapamaz.
tgcloud completion <bash|zsh|fish>
Standart çıktıya bir kabuk tamamlama komut dosyası yazdırır. Bir kez etkinleştirin, sonra <Sekme> komutları, bayrakları, modül dizinlerini, henüz sahip olmadığınız işleyici güncelleme türlerini ve yerel çalıştırılabilir modüllerinizi tamamlar.
# bash — bash-completion paketi gerekir:
echo 'eval "$(tgcloud completion bash)"' >> ~/.bashrc
# zsh — `autoload -U compinit && compinit`'in ~/.zshrc'nizde çalıştığından emin olun:
echo 'eval "$(tgcloud completion zsh)"' >> ~/.zshrc
# balık:
tgcloud completion fish > ~/.config/fish/completions/tgcloud.fish
Sonrasında kabuğunuzu yeniden başlatın (veya dosyayı yeniden kaynaklayın). Kabuk olmadan tgcloud completion çalıştırmak bu talimatları tekrar yazdırır.
upgrade
npx tgcloud upgrade [--dry-run]
CLI 0.2.0’dan önce oluşturulan projeler için tek seferlik geçiş, schema.js, lib/ ve handlers/‘ı proje kökünde tutuyordu. Bunları tgcloud/ içine taşır. Botla bağlantınız korunur ve yeniden dağıtım yapılması gerekmez. --dry-run planlanan hareketleri hiçbir şeye dokunmadan yazdırır. Diğer komutlar, yükseltene kadar eski düzen üzerinde çalışmaz.
Senkronize Kalma
Her projenin bulutta monotonik olarak artan bir revizyonu vardır, her dağıtımda artar. CLI, son senkronize olduğu revizyonu hatırlar ve her push‘ta gönderir. Bulut ilerlediyse — çünkü başka bir makine veya ekip üyesi dağıtım yaptıysa — itme, başka birinin işini sessizce üzerine yazmak yerine reddedilir ve CLI üç yol sunar:
npx tgcloud fetch # buluttaki değişiklikleri görün, sonra tekrar kontrol edin
npx tgcloud pull # en sonuncuyu çalışma dosyalarınıza getirin
npx tgcloud push --force # bulut durumunun üzerine yazın (tehlikeli)
Bu iyimser eşzamanlılık denetimi, bir kilitleme adımı dağıtım süreci olmadan bir botu bir ekip arasında paylaşabilmenizin nedenidir. Komutlar başarısız olduğunda sıfır olmayan bir çıkışla biter — reddedilen bir dağıtım, başarısız bir geçiş, bir kimlik doğrulama hatası, run sırasında hata veren bir modül — böylece komut dosyaları ve CI işlem hatlarında temiz bir şekilde birleşir.