Birkaç haftadır blogumu neredeyse tamamen otomatikleştirdim: her gün yeni bir yazı hazırlanıyor, ben Telegram’dan onaylıyorum, WordPress’e yayınlanıyor, sesli versiyonu oluşuyor ve LinkedIn’de paylaşılıyor — hepsi tek bir tetiklemeyle, benim tek bir “onayla” yazmam dışında elle dokunmadan. Bu yazıda bu sistemi nasıl kurduğumu, hangi araçları kullandığımı ve yolda karşılaştığım (ve çözdüğüm) gerçek sorunları paylaşıyorum. Amaç, benzer bir şey kurmak isteyenlere gerçekçi bir yol haritası vermek — bu yüzden API anahtarları, gerçek adresler ve kimlik bilgileri yerine temsili örnekler kullanacağım.
Genel Mimari
Sistem tek bir dev otomasyon değil, birbirine bağlı birkaç küçük n8n otomasyonundan oluşuyor. Her biri kendi işini yapıyor ve gerektiğinde bir diğerini tetikliyor:
- Günlük Yazı Otomasyonu — içeriği üretir, Telegram’dan onay alır, WordPress’e yayınlar
- Seslendirme Otomasyonu — yeni yayınlanan yazıyı otomatik seslendirip makaleye oynatıcı ekler
- LinkedIn Paylaşım Otomasyonu — yazıdan bir LinkedIn gönderisi türetip paylaşır
Bu üçü birbirinden bağımsız çalışabilir, ama WordPress’e bir yazı yayınlandığı anda diğer ikisi otomatik olarak tetikleniyor. Böylece “yaz, onayla, her şey halloluyor” hissi veriyor.
Adım 1: Yapay Zeka ile İçerik Üretimi
Her sabah bir Schedule Trigger düğümü otomasyonu başlatıyor. İlk iş, o günkü içerik türünü belirlemek — ben tek tip yazı (örneğin sadece haber özeti) yerine çeşitlilik istedim, bu yüzden basit bir rastgele seçim yapan bir Code düğümü kullanıyorum:
const types = ['gundem_ozeti', 'pratik_ipucu', 'sorun_cozumu', 'rehber'];
const secilen = types[Math.floor(Math.random() * types.length)];
return [{ json: { contentType: secilen } }];
Ardından bir AI Agent düğümü devreye giriyor. Bu düğüme bir dil modeli (OpenAI’nin web arama özelliği açık bir modeli) bağlı — böylece yazı gerçekten o günün güncel haberlerine dayanabiliyor, uydurma bilgi üretmiyor. Çıktının her zaman aynı yapıda (başlık, slug, içerik) gelmesi için bir Structured Output Parser alt düğümü ekledim; sistem talimatında JSON şeması örneği veriyorum:
{
"title": "Ornek Baslik",
"slug": "ornek-baslik",
"content": "<p>Makale govdesi HTML olarak...</p>"
}
Bizim için anlamı: Yapılandırılmış çıktı kullanınca yazının hangi alanının başlık, hangisinin içerik olduğunu tahmin etmek zorunda kalmıyorsunuz — ama dikkat: n8n’in Agent düğümü bu yapılandırılmış veriyi çoğu zaman output adında bir alt alanın İÇİNE koyuyor, düz üst seviyede değil. Bunu fark etmeden “title alanı boş geliyor” diye saatlerce debug ettim. Sonraki düğümde her iki ihtimali de kontrol eden bir savunma satırı eklemek işe yaradı:
const gelen = $input.first().json;
const veri = (gelen.output && typeof gelen.output === 'object') ? gelen.output : gelen;
Adım 2: Telegram Üzerinden Önizleme ve Onay
Yazı hazır olduğunda onu hemen yayınlamıyorum — önce görmek istiyorum. Burada n8n’in Telegram düğümünün sendAndWait operasyonu devreye giriyor. Bu özel bir düğüm: mesajı gönderiyor, “✅ Onayla” / “✏️ Değişiklik İste” butonlarını ekliyor ve workflow’u gerçekten duraklatıyor — siz bir butona basana kadar bekliyor, saatlerce bile olsa.
{
"resource": "message",
"operation": "sendAndWait",
"chatId": "SIZIN_TELEGRAM_CHAT_ID",
"responseType": "approval",
"chatApproval": true,
"approvalOptions": {
"values": { "approvalType": "double", "approveLabel": "✅ Onayla", "disapproveLabel": "✏️ Değişiklik İste" }
}
}
Bizim için anlamı: İlk denemede onay metnini serbest metin (yazarak “onayla” yazın) olarak kurmuştum — ama bu, Telegram’da butonlar yerine harici bir web formuna yönlendiren bir bağlantı gösteriyordu. “Telegram içinde kalmak” istiyorsanız responseType: "approval" ve chatApproval: true kombinasyonu şart; bu, onayı gerçek Telegram butonlarıyla, tarayıcıya hiç çıkmadan çözüyor.
Uzun makale metnini doğrudan Telegram mesajına gömmek de sorun çıkardı: hem mesaj çok uzun oluyor hem de kod örnekleri içindeki bazı karakterler (&&, <, > gibi) Telegram’ın varsayılan HTML ayrıştırıcısını kırıp mesajın hiç gitmemesine yol açıyordu. Çözüm iki parçalıydı: hem parse_mode alanını boş bırakmak (ayrıştırmayı kapatmak), hem de uzun metni mesaj yerine bir .txt dosyası olarak (Telegram’ın sendDocument operasyonuyla) göndermek.
Adım 3: Değişiklik Talebi Döngüsü
“Değişiklik İste” butonuna basınca ne oluyor? Burada işler biraz ilginçleşiyor, çünkü Telegram’ın onay mekanizması sadece buton tıklamalarını dinleyebiliyor, sıradan bir metin mesajını değil. Yani “ne değiştirmek istiyorsunuz?” diye sorduktan sonra gelecek cevabı YENİ bir otomasyon çalıştırması olarak yakalamam gerekiyordu:
- Kullanıcı “Değişiklik İste” butonuna basar
- Otomasyon mevcut taslağı küçük bir Data Table‘a kaydeder (“bekliyor: evet” bayrağıyla)
- Ayrı bir Telegram Trigger düğümü (herhangi bir mesajı dinleyen) kullanıcının bir sonraki mesajını yakalar
- Data Table’da bekleyen bir taslak var mı diye bakar — varsa, bu mesajı revizyon talebi olarak işler, taslağı yeniden yazar ve tekrar onaya sunar
Bizim için anlamı: Bu “bekleme durumu” deseni (bir tabloya “beklemede” yazıp sonraki mesajı buna göre yorumlamak) n8n’de gerçek bir konuşma akışı kurmanın pratik yolu — resmi bir “conversation state” özelliği olmadığı için kendi basit versiyonunuzu Data Table ile kurabilirsiniz.
Adım 4: WordPress’e Otomatik Yayın
Onay geldiğinde bir HTTP Request düğümü WordPress’in REST API’sine POST atıyor:
POST https://sizin-siteniz.com/wp-json/wp/v2/posts
Authorization: Basic BASE64(kullanici_adi:UYGULAMA_SIFRESI)
{
"title": "...",
"content": "...",
"status": "publish",
"categories": [3]
}
Buradaki kimlik doğrulama gerçek şifreniz değil, WordPress’in Uygulama Şifreleri (Application Passwords) özelliği — kullanıcı profilinizden üretebileceğiniz, iptal edilebilir, sadece API erişimi için geçerli ayrı bir şifre. Gerçek giriş şifrenizi hiçbir otomasyona vermeyin.
Adım 5: Zincirleme Tetikleme — Seslendirme ve LinkedIn
Yazı yayınlandıktan hemen sonra iki şeyin daha olmasını istiyorum: seslendirilmesi ve LinkedIn’de paylaşılması. Bunun için n8n’in Execute Sub-workflow düğümünü kullandım — bu düğüm başka bir otomasyonu “ateşle ve unut” (fire-and-forget) şeklinde tetikliyor, ana akışı bekletmeden:
{
"type": "Execute Sub-workflow",
"workflowId": "SESLENDIRME_OTOMASYONU_ID",
"options": { "waitForSubWorkflow": false }
}
Bizim için anlamı: Burada önemli bir teknik detay var — tetiklenecek otomasyonun İÇİNDE bir Execute Workflow Trigger düğümü olması gerekiyor, yoksa “Missing node to start execution” hatası alırsınız. Benim seslendirme otomasyonum zaten 3 saatte bir kendiliğinden çalışan bir Schedule Trigger ile kuruluydu; anlık tetikleme için bu ikinci trigger düğümünü EKLEDİM, mevcut zamanlayıcıyı kaldırmadım — n8n bir otomasyonda birden fazla tetikleyiciye izin veriyor, her biri bağımsız çalışıyor.
Adım 6: LinkedIn Paylaşımı
Ayrı bir otomasyon, günde bir kez (ve artık anlık tetiklemeyle) en son yayınlanan yazıları kontrol ediyor, daha önce paylaşılmamış olanları bir Data Table ile takip ediyor (tekrar paylaşmamak için), her biri için kısa bir AI Agent ile LinkedIn’e uygun bir özet metni yazdırıyor ve makalenin kapak görseliyle birlikte paylaşıyor.
Bizim için anlamı: Makale linkini AI’ın yazmasına GÜVENMEYİN — bazen ekliyor, bazen unutuyor, bazen yanlış formatlıyor. Ben linki AI’dan tamamen çıkardım ve bir Code düğümüyle gönderi metninin sonuna programatik olarak ekliyorum: metin + '\n\n🔗 ' + gercekLink. Garantili ve tutarlı.
Adım 7: Seslendirme
Yeni yazı, Google Cloud Text-to-Speech API’sine (en doğal ses kalitesi için “HD” tier bir ses seçtim) gönderiliyor, dönen ses dosyası WordPress medya kütüphanesine yükleniyor ve makalenin başına küçük bir oynatıcı ekleniyor.
Bizim için anlamı: Uzun makaleler TTS API’lerinin tek seferde kabul ettiği karakter sınırını aşabiliyor. Metni cümle sınırlarına saygı göstererek parçalara bölüp her parçayı ayrı ayrı seslendirip sonra ses dosyalarını Buffer.concat() ile birleştirmek gerekiyor. Ayrıca İngilizce teknik terimlerin (API, TLS, Postfix gibi) Türkçe fonetikle tuhaf okunması bir sorun oldu — bunun için metni SSML’e çevirip bilinen teknik terimleri <lang xml:lang="en-US">terim</lang> etiketiyle işaretleyerek o kelimelerde İngilizce telaffuza geçmesini sağlamaya çalışıyorum.
Yolda Öğrendiğim Genel Dersler
- Her zaman canlı test edin: Bir otomasyonun “başarılı” görünmesi, gerçekten doğru içerik ürettiği anlamına gelmez. Yayınlanan sayfayı gerçekten açıp kontrol etmek, boş başlıklı veya bozuk içerikli gönderileri erken yakalamanın tek yolu.
- Paralel dallara dikkat: Bir düğümün çıktısı birden fazla yöne bağlıysa (örneğin hem görsel oluşturma hem dosya gönderme), bu dalların sırası garantili değildir. Kullanıcı deneyimi sıraya bağlıysa (önce metin, sonra görsel, sonra onay gibi) düğümleri paralel değil, art arda bağlayın.
- 0 öğe normal bir durumdur: Bir düğüm hiçbir sonuç döndürmediğinde n8n sonraki düğümleri atlar — bu genelde doğru davranıştır (“bu turda yeni bir şey yok”), yapay olarak boş bir öğe zorlamayın, aksi halde sonraki düğümler
undefinedalanlarla çökmeye başlar. - Kimlik bilgilerini asla workflow koduna gömmeyin: n8n’in kendi Credential sistemini kullanın. Bu hem güvenlik hem de “bir anahtar değiştiğinde tek yerden güncelleme” kolaylığı sağlıyor.
Bu Rehberin Çıkarımı
Bu sistemi tek seferde kurmadım — haftalar içinde, her hatadan bir şey öğrenerek parça parça inşa ettim. Eğer siz de benzer bir şey kurmayı düşünüyorsanız, tavsiyem küçük başlamak: önce tek bir otomasyonu (örneğin sadece içerik üretimi ve Telegram onayı) sağlam bir şekilde çalıştırın, sonra üstüne WordPress yayınını, sonra zincirleme tetiklemeleri ekleyin. Her adımda gerçekten neyin yayınlandığını kontrol edin — otomasyona güvenmek ile otomasyonu doğrulamak arasındaki fark, bu projede beni en çok kurtaran alışkanlık oldu.