This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
# Social Poster Modülü — Otomatik Sosyal Medya Paylaşım Sistemi
|
||||
|
||||
Son güncelleme: 1 Mart 2026
|
||||
|
||||
---
|
||||
|
||||
## 1. Amaç
|
||||
|
||||
Top liglerdeki maçların AI tahminlerini **otomatik olarak görselleştirip** Instagram, Facebook ve X (Twitter) üzerinden paylaşmak. Her maç için 30 dakika önceden tahmin alınıp, 1080×1920 (9:16 Instagram Story) formatında poster üretilir.
|
||||
|
||||
---
|
||||
|
||||
## 2. Mimari Akış
|
||||
|
||||
```
|
||||
Cron (*/10 dk) → LiveMatch sorgusu (top_leagues.json filtresi)
|
||||
→ AI Engine V20+ POST /v20plus/analyze/{match_id}
|
||||
→ PredictionCardDto oluştur
|
||||
→ Node Canvas ile 1080x1920 PNG render
|
||||
→ Gemini ile Türkçe caption üret
|
||||
→ Twitter / Facebook / Instagram API'ye paylaş
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Dosya Yapısı
|
||||
|
||||
```
|
||||
src/modules/social-poster/
|
||||
├── social-poster.module.ts # NestJS modül tanımı
|
||||
├── social-poster.controller.ts # Test endpointleri (preview, post)
|
||||
├── social-poster.service.ts # Ana orkestrasyon servisi
|
||||
├── image-renderer.service.ts # Node Canvas ile görsel üretimi
|
||||
├── caption-generator.service.ts # Gemini ile post metni üretimi
|
||||
├── twitter.service.ts # Twitter/X API entegrasyonu
|
||||
├── meta.service.ts # Facebook + Instagram Graph API
|
||||
└── dto/
|
||||
└── prediction-card.dto.ts # PredictionCardDto, TopPick, SocialPostResult
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Temel Servisler
|
||||
|
||||
### 4.1 SocialPosterService
|
||||
|
||||
**Cron:** Her 10 dakikada bir çalışır. 25–40 dakika içinde başlayacak maçları `top_leagues.json` filtresiyle bulur.
|
||||
|
||||
**Pipeline:** `predictAndPost(match)` → Tahmin al → Görsel üret → Caption üret → Paylaş
|
||||
|
||||
**AI Engine İsteği:**
|
||||
```typescript
|
||||
// POST — GET değil! AI Engine v20plus POST bekler.
|
||||
axios.post(`${aiEngineUrl}/v20plus/analyze/${matchId}`, null, { timeout: 30000 })
|
||||
```
|
||||
|
||||
**Veri Haritalandırma (V20+ → CardDto):**
|
||||
|
||||
| V20+ Response Alanı | CardDto Alanı |
|
||||
|---|---|
|
||||
| `score_prediction.ht` | `htScore` (ör: "1-1") |
|
||||
| `score_prediction.ft` | `ftScore` (ör: "2-1") |
|
||||
| `main_pick.confidence` | `scoreConfidence` (ör: 65) |
|
||||
| `bet_summary[]` (array) | `topPicks[]` (ilk 3, confidence'a göre sıralı) |
|
||||
| `risk.level` | `riskLevel` (LOW/MEDIUM/HIGH/EXTREME) |
|
||||
| `match_info.home_team` | `homeTeam` (fallback) |
|
||||
|
||||
**Bet Summary Market Kodları:**
|
||||
|
||||
| Kod | Türkçe | English |
|
||||
|---|---|---|
|
||||
| MS | Maç Sonucu | Match Result |
|
||||
| OU15 | Üst 1.5 Gol | Over 1.5 |
|
||||
| OU25 | Üst 2.5 Gol | Over 2.5 |
|
||||
| OU35 | Üst 3.5 Gol | Over 3.5 |
|
||||
| BTTS | Karşılıklı Gol | Both Teams Score |
|
||||
| DC | Çifte Şans | Double Chance |
|
||||
| HT | İlk Yarı Sonucu | Half Time Result |
|
||||
| HT_OU05 | İY 0.5 Üst/Alt | HT Over/Under 0.5 |
|
||||
| OE | Tek/Çift | Odd/Even |
|
||||
| HTFT | İY/MS | HT/FT |
|
||||
|
||||
### 4.2 ImageRendererService
|
||||
|
||||
**Motor:** `node-canvas` (Puppeteer/HTML yok — sunucu performansı için)
|
||||
|
||||
**Çıktı:** `public/predictions/prediction_{matchId}_{timestamp}.png`
|
||||
|
||||
**Boyut:** 1080×1920 px (Instagram Story / Reels uyumlu)
|
||||
|
||||
**Özellikler:**
|
||||
- Koyu gradient arka plan (#0a0e27 → #1a1040 → #0d1b2a)
|
||||
- Lig adı + tarih başlık satırı
|
||||
- Takım logoları (200×200px) — `public/uploads/teams/` altından okunur
|
||||
- İlk Yarı / Maç Sonu skor kutuları
|
||||
- Güven yüzdesi badge'i
|
||||
- En iyi 3 tahmin (progress bar + yüzde)
|
||||
- Risk seviyesi badge'i (renk kodlu)
|
||||
- `iddaai.com` filigran (saydam, tekrarlı, döndürülmüş)
|
||||
- Alt bilgi: "⚡ AI Powered by SuggestBet"
|
||||
|
||||
**Logo Çözümleme:**
|
||||
```
|
||||
1. Yerel dosya varsa → public/uploads/teams/xxx.png oku
|
||||
2. URL http ile başlıyorsa → HTTP ile indir
|
||||
3. Bulunamazsa → logo olmadan devam et (graceful fallback)
|
||||
```
|
||||
|
||||
### 4.3 CaptionGeneratorService
|
||||
|
||||
Gemini API kullanarak maç verisi JSON'ından Türkçe post metni üretir.
|
||||
|
||||
### 4.4 TwitterService & MetaService
|
||||
|
||||
Üretilen görsel + caption'ı ilgili platformlara yükler.
|
||||
|
||||
---
|
||||
|
||||
## 5. API Endpointleri
|
||||
|
||||
| Method | Path | Auth | Açıklama |
|
||||
|---|---|---|---|
|
||||
| GET | `/api/social-poster/preview/:matchId` | @Public | Sadece görsel üret + caption üret (paylaşma) |
|
||||
| POST | `/api/social-poster/post/:matchId` | @Public | Görsel üret + caption üret + tüm platformlara paylaş |
|
||||
|
||||
> **Not:** Test endpointleri `@Public()` dekoratörüyle auth bypass edilmiştir. Production'da kaldırılmalı veya admin-only yapılmalıdır.
|
||||
|
||||
---
|
||||
|
||||
## 6. Environment Değişkenleri
|
||||
|
||||
| Key | Zorunlu | Varsayılan | Açıklama |
|
||||
|---|---|---|---|
|
||||
| `AI_ENGINE_URL` | ✅ | `http://localhost:8000` | AI Engine base URL |
|
||||
| `APP_BASE_URL` | ✅ | `http://localhost:3000` | Logo URL çözümleme için |
|
||||
| `SOCIAL_POSTER_ENABLED` | ❌ | `false` | Cron job'ı aktif/pasif |
|
||||
| `GOOGLE_API_KEY` | ❌ | — | Gemini caption için |
|
||||
| Twitter API keys | ❌ | — | Twitter paylaşım için |
|
||||
| Meta API keys | ❌ | — | FB/IG paylaşım için |
|
||||
|
||||
---
|
||||
|
||||
## 7. Bağımlılıklar
|
||||
|
||||
```json
|
||||
{
|
||||
"canvas": "^2.x", // Node Canvas — görsel üretimi
|
||||
"axios": "^1.x", // HTTP istekleri (AI Engine + logo indirme)
|
||||
"@nestjs/schedule": "*" // Cron job desteği
|
||||
}
|
||||
```
|
||||
|
||||
> **Kaldırılan:** `puppeteer` — performans ve Raspberry Pi uyumluluğu için `canvas` ile değiştirildi.
|
||||
|
||||
---
|
||||
|
||||
## 8. Deploy Notları
|
||||
|
||||
### Raspberry Pi (ARM64)
|
||||
|
||||
```bash
|
||||
# canvas native bağımlılıkları (Dockerfile'da)
|
||||
RUN apk add --no-cache cairo-dev pango-dev jpeg-dev giflib-dev librsvg-dev
|
||||
```
|
||||
|
||||
### Port Yönetimi
|
||||
|
||||
| Servis | Port |
|
||||
|---|---|
|
||||
| NestJS Backend | 3000 (production: 150X) |
|
||||
| AI Engine | 8000 (dev: 8005 — Windows port kısıtlaması) |
|
||||
|
||||
### Dosya Sistemi
|
||||
|
||||
```
|
||||
public/
|
||||
├── uploads/teams/ # Takım logoları (PNG)
|
||||
└── predictions/ # Üretilen poster görselleri (PNG)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Bilinen Sorunlar & Çözümler
|
||||
|
||||
| Sorun | Sebep | Çözüm |
|
||||
|---|---|---|
|
||||
| `WinError 10013` port erişim hatası | Windows Hyper-V port rezervasyonu | Farklı port kullan (8005) |
|
||||
| `Invalid prisma.liveMatch.findUnique()` | Prisma client eskimiş | `npx prisma generate` çalıştır |
|
||||
| `405 Method Not Allowed` AI Engine | GET yerine POST gerekiyor | `axios.post()` kullan |
|
||||
| Logolar görünmüyor (lokal dev) | Logo dosyaları sunucuda, lokalde yok | Deploy'da çalışır, lokal'de graceful skip |
|
||||
Reference in New Issue
Block a user