Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Yazı Tipi BoyutlandırıcıAa
  • Anasayfa
  • Teknoloji
    • Siber Güvenlik
    • Yapay Zeka
    • Donanım
    • Bilim
  • Yazılım
  • Savunma & İstihbarat
  • Oyun
  • Yaşam
    • Finans
    • Sinema
    • Dünyadan Haberler
  • İş Birliği
Okuma: Açık Kaynak Bir Sosyal Medya Planlayıcısını Laravel ile Nasıl Geliştirdim
Paylaş
Yazı Tipi BoyutlandırıcıAa
Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Ara
Bizi Takip Et
  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti
© 2026 Teknomers. All Rights Reserved.

Anasayfa » Açık Kaynak Bir Sosyal Medya Planlayıcısını Laravel ile Nasıl Geliştirdim

Yazılım

Açık Kaynak Bir Sosyal Medya Planlayıcısını Laravel ile Nasıl Geliştirdim

teknomers
Son güncelleme: 27 Mayıs 2026 21:26
teknomers
Paylaş
Paylaş

Yazılım işleriyle ilgili doğru ve tutarlı bir planlama yapmak, süreçlerinizi optimize etmek açısından önemlidir. Sosyal medya gönderimlerini düzenlemek için birçok araç mevcut; ancak çoğu, taslaklarınızın, analizlerinizin ve bağlı hesaplara ait erişim token’larının sunucularında tutulmasını gerektirir. Bu sebeple, açık kaynak bir alternatif olarak TryPost projesini geliştirdim.

TryPost, API üzerinden 10 farklı sosyal medya ağıyla iletişim kurabilen bir platformdur (X, LinkedIn, Facebook, Instagram, TikTok, YouTube, Pinterest, Threads, Bluesky, Mastodon) ve tüm bunları kendi sunucularınızda ücretsiz olarak çalıştırmanıza olanak tanır.

Bu makalede, uygulamanın temel yapı taşlarını, sağlayıcı soyutlamasını, OAuth ve token yenileme işlevini, zamanlama sürecini ve daha fazlasını ele alacağız.


Bir derleyici, on sosyal ağ

Her sosyal medya platformu, API, limitler ve “gönderi” anlayışı açısından farklılık göstermektedir. Örneğin, X platformu 280 karakter, LinkedIn ise 3000 karakter kabul etmektedir. İçerik yönetimini tek bir yerde tutmak adına, platform bilgilerini bir enum yapısında saklıyorum:

enum Platform: string
{
    case X = 'x';
    case LinkedIn = 'linkedin';
    case Instagram = 'instagram';
    case Threads = 'threads';
    case Bluesky = 'bluesky';
    // ...diğer sosyal ağlar

    public function maxContentLength(): int
    {
        return match ($this) {
            self::X => 280,
            self::LinkedIn => 3000,
            // ...
        };
    }

    public function queue(): string
    {
        return "social-{$this->value}";
    }
}

Her bir ağ için, yalnızca bir API ile konuşan özel bir Publisher sınıfı oluşturulmakta ve doğru sınıf yayın anında seçilmektedir:

private function publisher(): SocialPublisher
{
    return match ($this->postPlatform->platform) {
        Platform::X         => app(XPublisher::class),
        Platform::LinkedIn  => app(LinkedInPublisher::class),
        Platform::Instagram => app(InstagramPublisher::class),
        // ...her ağ için bir satır
    };
}

Her bir publisher benzer yapıyı kullanmakta; gönderiyi alır ve bir ID ile URL döner:

class XPublisher
{
    use HasSocialHttpClient; // ortak HTTP istemcisi, doğrulama, tekrar denemeler

    public function publish(PostPlatform $postPlatform): array
    {
        $this->validateContentLength($postPlatform);

        $response = $this->http($postPlatform->socialAccount)
            ->post("{$this->baseUrl}/tweets", [
                'text' => $postPlatform->content,
            ]);

        return [
            'id'  => $response->json('data.id'),
            'url' => "https://x.com/i/web/status/{$response->json('data.id')}",
        ];
    }
}

Yeni bir sosyal ağ eklemek artık bilinen bir kontrol listesi ile yapılmaktadır: enum’a bir durum ekleyin, bir publisher yazın ve match içinde kaydedin. Takvim, derleyici ve zamanlayıcı hiç değişmeyecek.


OAuth ve token yenileme tuzağı

Hesaplara bağlanma işlemleri OAuth ile gerçekleştirilir; işlem Laravel Socialite ile yönetilir. Token’lar hassas verilerdir, bu nedenle veritabanında açık metin olarak bulunmazlar. Laravel’in encrypted cast’i bu işlemi şeffaf şekilde yönetir:

protected function casts(): array
{
    return [
        'access_token'     => 'encrypted',
        'refresh_token'    => 'encrypted',
        'token_expires_at' => 'datetime',
        'scopes'           => 'array',
    ];
}

Çözülmesi gereken ilginç bir durum ise yenileme yarışları. Bazı platformlar, token’ınızı her kullandığınızda döndürür; buna göre bir çalışma alanında beş planlanmış gönderi her yarım dakikada bir yayınlanmak için belirlenirse, beş iş her biri token’ın geçersiz olduğunu fark eder ve hepsi yenileme çağrısı yapar. Nine zaman bu yarıştan biri başarılı olurken, diğerleri “geçersiz token” mesajı alır ve sağlıklı bir hesabı disoiliyorlar.

İki kural bu durumu düzeltir. İlk olarak, yenilemeyi öncelikle denemek ve yalnızca bir 401 hatası aldığınızda yenilemek:

public function publishWithFreshToken(PostPlatform $postPlatform): array
    {
        try {
            return $this->publisher()->publish($postPlatform);
        } catch (TokenExpiredException) {
            $this->refreshToken($postPlatform->socialAccount);

            return $this->publisher()->publish($postPlatform);
        }
    }

İkinci olarak, bir yenileme gerektiğinde, sadece bir işin token’ı döndürmesini sağlamak ve diğer işlerin sonucu yeniden kullanmasını sağlamak için bunu bir kilitle seri hale getirmekte fayda vardır:

public function refreshToken(SocialAccount $account): void
    {
        $lock = Cache::lock("token-refresh:{$account->id}", 30);

        if (! $lock->get()) {
            $account->refresh(); // başkası döndürüyor, onlarınkini kullanın
            return ;
        }

        try {
            match ($account->platform) {
                Platform::LinkedIn => $this->refreshLinkedIn($account),
                Platform::X        => $this->refreshX($account),
                // ...
            };
        } finally {
            $lock->release();
        }
    }


Zamanlama: cron → kuyruk → yayımla

Zamanlayıcı kendisi oldukça basit, bu da amaç. Her dakika, gönderileri bulur ve her biri için bir iş gönderir:

// routes/console.php
Schedule::command(ProcessScheduledPosts::class)
    ->everyMinute()
    ->withoutOverlapping()
    ->onOneServer();

Önemli olan detay, bir gönderinin tam olarak bir kez yayımlanmasını sağlamak. Bunu koşullu bir UPDATE kullanarak yapıyorum. Her işi koşullu olarak güncellemenin atomik bir durumu elde eder:

public function handle(): void
{
    Post::query()->due()->each(function (Post $post) {
        $claimed = Post::whereKey($post->id)
            ->where(, Status::Scheduled)
            ->update([=> Status::Publishing]);

        if ($claimed === 1) {
            PublishPost::dispatch($post);
        }
    });
}

İşlemin yalnızca UPDATE işlemi düzgün bir şekilde Scheduled‘dan Publishing‘e geçiyorsa yayımlanmasına izin verilir. Diğer tüm işlemler sıfır etkilenen satır görerek yoluna devam eder. Yani dağıtılmış kilitlenmeye gerek yok, ekstra bir altyapı kurmaya gerek yok; yalnızca bir koşullu güncelleme yeterlidir.

İş süreci Horizon ile genişler. Her platform için bir kuyruk (örneğin, social-x, social-linkedin, …) vardır. Bu izolasyon önemlidir; eğer Instagram API yavaş çalışıyorsa, o kuyruk üzerindeki işler birikmetedir; diğerleri etkilenmez. Ayrıca, yayımlama işi idempotandır; bu, bir deneme asla çift yayımlama yapmamalıdır:

public function __construct(public PostPlatform $postPlatform)
{
    $this->onQueue($postPlatform->platform->queue());
}

public function handle(): void
{
    if ($this->postPlatform->status === Status::Published) {
        return; // zaten tamamlandı, bu nedenle yeniden deneme bir no-op
    }

    // yenileme dikkate alınarak yayımla, ardından yayımlandı veya başarısız durumda işaretle
}

Bir gönderi birden fazla sosyal ağı hedefleyebilir ve bunlar bağımsız olarak başarılı olabilir. Dolayısıyla, bir gönderi sadece “yayınlandı” veya “başarısız” değildir. Kısmi yayınlama olasılığı vardır (X gönderilmiş, Instagram resmi reddetmiştir) ve UI hangi kısmın dikkat gerektirdiğini gösterir.


Çalışma alanları ile çok kiracılık

TryPost, ajanslar ve ekipler için oluşturulmuştur, bu nedenle çalışma alanı izolasyonu veri katmanında zorunlu hale getirilmiştir. Üç katmandan oluşmaktadır. Hesap, faturalandırma varlığıdır. Bir çalışma alanı ise içerik silo’sudur: bir marka veya bir müşteriyle ilişkili, kendi sosyal hesapları, gönderileri, marka sesi ve üyeleri bulunmaktadır. Diğer her şey (gönderiler, sosyal hesaplar, etiketler) bir çalışma alanına bağlıdır.

class Workspace extends Model
{
    public function account(): BelongsTo
    {
        return $this->belongsTo(Account::class);
    }

    public function socialAccounts(): HasMany
    {
        return $this->hasMany(SocialAccount::class);
    }

    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }
}

Her şey workspace_id taşıdığı için, mevcut çalışma alanına göre sorgu yapmak, bir müşterinin verisinin başka birinin verisine sızmasını önler. Ve sistem kendi kendine barındırılabilir olduğundan, faturalandırma tek bir anahtar ile sağlanmaktadır. Kendi kendine barındırılan kurulumlar burada tamamen devre dışı kalmaktadır:

public function hasActiveSubscription(): bool
{
    if (config()) {
        return true;
    }

    return $this->subscribed();
}


MCP Sunucusu Olarak Beklemediğim Kısım

Normal bir REST API’nin yanı sıra, TryPost bir MCP sunucusu ile birlikte gelir, böylece Claude, Cursor veya ChatGPT gibi bir AI asistanı, doğrudan doğal dil kullanarak uygulamayı çalıştırabilir. “Salı günü saat 09:00 için bir LinkedIn gönderisi taslağı oluştur ve programla” komutu gerçekten çalışmaktadır.

Laravel, şimdi MCP desteği sunuyor, bu nedenle sunucu sadece araçlarını listeleyen bir sınıf. Örnek kullanım:

#[Name('TryPost')]
#[Instructions('Sosyal gönderileri planla, yayımlama ve metrikleri al.')]
class TryPostServer extends Server
{
    protected array $tools = [
        ListPostsTool::class,
        CreatePostTool::class,
        PublishPostTool::class,
        GetPostMetricsTool::class,
        // ...25+ araç, panelde sahip olduğunuz aynı eylemler
    ];
}
// routes/ai.php
Mcp::web(, TryPostServer::class)
    ->middleware([, ]);

Her araç, bir tür şemayla, doğrulama ve aynı web arayüzünde kullanılan eylemleri çağıran bir işleyici ile birlikte küçük bir sınıftır, böylece ikinci bir uygulama senkronize tutmaya gerek kalmaz. Kimlik doğrulama middleware’i, isteği doğru çalışma alanına bağlar, böylece bir asistan yalnızca kendi token’ına bağlı verilere erişebilir.

“Bir gönderi taslağı oluştur” kütüphanesi, yapılandırılmış bir çıktı kullanılarak düzenlenir, böylece model serbest metin döndüremez. Bu nedenle, döndürülen çıktının şemasında bir başlık, resim destesi ve anahtar kelimeler bulunmaktadır. Marka sesi (ton, dil, örnekler) çalışma alanından gelir ve istemlerin kendisi PHP dizeleri yerine Blade şablonlarına gömülür, böylece kodu değiştirmeden düzenlenebilir.

public function schema(JsonSchema $schema): array
{
    return [
        => ->string()->required(),
        => ->string()->required(),
        => ->array()->items(->string())->required(),
    ];
}

Özetle, temiz bir API yüzeyi olan bir zamanlayıcı, AI ajanlarının işlem yapabilmesi için gereken temel yapı taşlarını oluşturur. MCP katmanı, mevcut olan yapıların üzerine sadece birkaç yüz satır eklenerek oluşturulmuştur.


Deneyin

Burası, enum odaklı platformlar, yenileme korumalı, güvenli token’lar, Horizon üzerinde atomik bir zamanlayıcı, çalışma alanı izolasyonu ve UI ile aynı işlevlerin yer aldığı bir MCP sunucusu ile oluşturulmuş platformun temelini oluşturmaktadır.

Tüm proje açık kaynaklıdır ve AGPL lisansına sahiptir. Her satırını okuyabilir, çatal alabilir veya kendiniz ücretsiz olarak çalıştırabilirsiniz:

⭐ GitHub’da yıldızlayın: github.com/trypostit/trypost
🏠 Kendinize barındırın (ücretsiz, sonsuza kadar): docs.trypost.it

Yıldızlar, bu tür projelerin keşfedilmesinin ana yoludur, bu nedenle TryPost sizin için faydalıysa bir yıldız verebilirseniz gerçekten takdir ederim.

Bir sunucu çalıştırmak istemiyorsanız, aynı kod tabanına sahip barındırılan bir sürüm de bulunmaktadır: trypost.it.

Herkese iyi kodlamalar.

Kaynak: Orijinal Makale

Contents
  • Bir derleyici, on sosyal ağ
  • OAuth ve token yenileme tuzağı
  • Zamanlama: cron → kuyruk → yayımla
  • Çalışma alanları ile çok kiracılık
  • MCP Sunucusu Olarak Beklemediğim Kısım
  • Deneyin
Laravel 13’ün Yapay Zeka Geliştirme Üzerindeki Değişiklikleri
Yapay Zeka Ortakları ile Laravel Paketi Oluşturma ve Savaş Testi Yapma
cPanel’de Laravel storage:link Çalışmıyor mu? Dağıtım Sonrası Görseller Kayboluyor
Laravel esintili hafif bir PHP MVC çerçevesi olan Larite’i geliştirdim. Deneyimli geliştiricilerden geri bildirim almak isterim.
Maravel-Framework 10.68 Otomatik Bağlama Varsayılan Parametre Önceliği Anahtarı
Bu Makaleyi Paylaş
Facebook Bağlantıyı Kopyala Yazdır
Paylaş
Önceki Makale 37 Yıl Sonra Retro Oyun Devamı Yayınlandı – Colin Porch’un Hikayesi
Sonraki Makale Dating Uygulaması, Çıkmak İçin Ücretsiz Yakıt Dağıtıyor!

Sanal Medya

FacebookBeğen
452Takip Et
PinterestSabitle
237Takip Et

Son Eklenenler

Kaspersky, Steam Wallpaper Engine’da hesapları ele geçiren zararlı yazılım buldu
Donanım
Dijital girişimci Raspberry Pi ile mizahi fiziksel NFT cihazı yaptı
Donanım
Telegram’ın Hindistan’daki Yasağı VPN ve Rakip Uygulamalara Talebi Artırdı
Genel
Elastic, CRV destekli DeductiveAI’yi 85M$’ye alıyor
Yapay Zeka
Trump, Apple’ın Intel ile çip üretimi için anlaştığını açıkladı
Donanım

MapTap, günlük bir coğrafya oyunu, benim yeni Wordle’ım oldu

Yeni Bir Eğlence: Coğrafya Oyunu MapTap ile Tanışın

Genel
//

Siber güvenlik, yapay zeka ve savunma sanayiinden; finans ve sinema dünyasına uzanan geniş bir yelpaze. Teknomers; teknoloji, strateji ve yazılım dünyasını sade bir dille sizlerle buluşturuyor.

Kurumsal

  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti

Kategoriler

  • Teknoloji
  • Oyun
  • Sinema
  • Siber Güvenlik
  • Bilim
  • Finans
  • Dünyadan Güncel Haberler

Populer

  • TV'de Ücretsiz İzlenebilen Şifresiz Erotik Kanallar (2025 Güncel Frekans Listesi)

  • The Last of Us PC Kontrolleri: Hızlı Silah Değiştirme ve Tüm Tuşlar (2025)

  • Hogwarts Legacy'de Odaklanma İksiri Nasıl Yapılır?

Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Bizi Takip Et
© 2026 Teknomers. All Rights Reserved.
Welcome Back!

Sign in to your account

Kullanıcı Adı veya E-posta Adresi
Şifre

Şifrenizi mi unuttunuz?