const admin = require('firebase-admin'); let firebaseApp = null; /** * Firebase Admin SDK'yı başlat */ const initializeFirebase = () => { try { // Eğer zaten başlatılmışsa, mevcut instance'ı döndür if (firebaseApp) { return firebaseApp; } // Environment variables'dan Firebase config'i al const firebaseConfig = { type: process.env.FIREBASE_TYPE, project_id: process.env.FIREBASE_PROJECT_ID, private_key_id: process.env.FIREBASE_PRIVATE_KEY_ID, private_key: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'), client_email: process.env.FIREBASE_CLIENT_EMAIL, client_id: process.env.FIREBASE_CLIENT_ID, auth_uri: process.env.FIREBASE_AUTH_URI, token_uri: process.env.FIREBASE_TOKEN_URI, auth_provider_x509_cert_url: process.env.FIREBASE_AUTH_PROVIDER_X509_CERT_URL, client_x509_cert_url: process.env.FIREBASE_CLIENT_X509_CERT_URL }; // Gerekli environment variables'ların varlığını kontrol et const requiredFields = ['project_id', 'private_key', 'client_email']; const missingFields = requiredFields.filter(field => !firebaseConfig[field]); if (missingFields.length > 0) { console.warn(`⚠️ Firebase konfigürasyonu eksik: ${missingFields.join(', ')}`); console.warn('Push notification özelliği devre dışı bırakıldı.'); return null; } // Firebase Admin SDK'yı başlat firebaseApp = admin.initializeApp({ credential: admin.credential.cert(firebaseConfig), projectId: firebaseConfig.project_id }); console.log('✅ Firebase Admin SDK başarıyla başlatıldı'); return firebaseApp; } catch (error) { console.error('❌ Firebase başlatma hatası:', error.message); console.warn('Push notification özelliği devre dışı bırakıldı.'); return null; } }; /** * Firebase Messaging instance'ını al */ const getMessaging = () => { if (!firebaseApp) { console.warn('Firebase başlatılmamış. Push notification gönderilemez.'); return null; } try { return admin.messaging(); } catch (error) { console.error('Firebase Messaging alınamadı:', error); return null; } }; /** * Tek bir cihaza push notification gönder * @param {string} token - Device token * @param {object} notification - Notification objesi * @param {object} data - Ek veri * @returns {Promise} Gönderim sonucu */ const sendToDevice = async (token, notification, data = {}) => { const messaging = getMessaging(); if (!messaging) { return { success: false, error: 'Firebase Messaging kullanılamıyor' }; } try { const message = { token: token, notification: { title: notification.title, body: notification.body, ...(notification.imageUrl && { imageUrl: notification.imageUrl }) }, data: { ...data, timestamp: new Date().toISOString() }, android: { notification: { icon: 'ic_notification', color: '#FF5722', sound: 'default', priority: 'high' } }, apns: { payload: { aps: { sound: 'default', badge: 1 } } } }; const response = await messaging.send(message); return { success: true, messageId: response, token: token }; } catch (error) { console.error('Push notification gönderme hatası:', error); // Token geçersizse, bu bilgiyi döndür if (error.code === 'messaging/registration-token-not-registered' || error.code === 'messaging/invalid-registration-token') { return { success: false, error: 'Invalid token', invalidToken: true, token: token }; } return { success: false, error: error.message, token: token }; } }; /** * Birden fazla cihaza push notification gönder * @param {string[]} tokens - Device token'ları * @param {object} notification - Notification objesi * @param {object} data - Ek veri * @returns {Promise} Gönderim sonucu */ const sendToMultipleDevices = async (tokens, notification, data = {}) => { const messaging = getMessaging(); if (!messaging) { return { success: false, error: 'Firebase Messaging kullanılamıyor' }; } if (!tokens || tokens.length === 0) { return { success: false, error: 'Token listesi boş' }; } try { const message = { notification: { title: notification.title, body: notification.body, ...(notification.imageUrl && { imageUrl: notification.imageUrl }) }, data: { ...data, timestamp: new Date().toISOString() }, android: { notification: { icon: 'ic_notification', color: '#FF5722', sound: 'default', priority: 'high' } }, apns: { payload: { aps: { sound: 'default', badge: 1 } } }, tokens: tokens }; const response = await messaging.sendMulticast(message); // Başarısız token'ları topla const failedTokens = []; const invalidTokens = []; response.responses.forEach((resp, idx) => { if (!resp.success) { const token = tokens[idx]; failedTokens.push({ token, error: resp.error?.message }); if (resp.error?.code === 'messaging/registration-token-not-registered' || resp.error?.code === 'messaging/invalid-registration-token') { invalidTokens.push(token); } } }); return { success: response.successCount > 0, successCount: response.successCount, failureCount: response.failureCount, failedTokens: failedTokens, invalidTokens: invalidTokens }; } catch (error) { console.error('Toplu push notification gönderme hatası:', error); return { success: false, error: error.message }; } }; /** * Topic'e push notification gönder * @param {string} topic - Topic adı * @param {object} notification - Notification objesi * @param {object} data - Ek veri * @returns {Promise} Gönderim sonucu */ const sendToTopic = async (topic, notification, data = {}) => { const messaging = getMessaging(); if (!messaging) { return { success: false, error: 'Firebase Messaging kullanılamıyor' }; } try { const message = { topic: topic, notification: { title: notification.title, body: notification.body, ...(notification.imageUrl && { imageUrl: notification.imageUrl }) }, data: { ...data, timestamp: new Date().toISOString() }, android: { notification: { icon: 'ic_notification', color: '#FF5722', sound: 'default', priority: 'high' } }, apns: { payload: { aps: { sound: 'default', badge: 1 } } } }; const response = await messaging.send(message); return { success: true, messageId: response, topic: topic }; } catch (error) { console.error('Topic push notification gönderme hatası:', error); return { success: false, error: error.message, topic: topic }; } }; /** * Cihazı topic'e abone et * @param {string[]} tokens - Device token'ları * @param {string} topic - Topic adı * @returns {Promise} Abonelik sonucu */ const subscribeToTopic = async (tokens, topic) => { const messaging = getMessaging(); if (!messaging) { return { success: false, error: 'Firebase Messaging kullanılamıyor' }; } try { const response = await messaging.subscribeToTopic(tokens, topic); return { success: response.successCount > 0, successCount: response.successCount, failureCount: response.failureCount, errors: response.errors }; } catch (error) { console.error('Topic abonelik hatası:', error); return { success: false, error: error.message }; } }; /** * Cihazın topic aboneliğini iptal et * @param {string[]} tokens - Device token'ları * @param {string} topic - Topic adı * @returns {Promise} Abonelik iptal sonucu */ const unsubscribeFromTopic = async (tokens, topic) => { const messaging = getMessaging(); if (!messaging) { return { success: false, error: 'Firebase Messaging kullanılamıyor' }; } try { const response = await messaging.unsubscribeFromTopic(tokens, topic); return { success: response.successCount > 0, successCount: response.successCount, failureCount: response.failureCount, errors: response.errors }; } catch (error) { console.error('Topic abonelik iptal hatası:', error); return { success: false, error: error.message }; } }; /** * Firebase durumunu kontrol et * @returns {object} Firebase durum bilgisi */ const getStatus = () => { return { initialized: !!firebaseApp, messaging: !!getMessaging(), projectId: firebaseApp?.options?.projectId || null }; }; module.exports = { initializeFirebase, getMessaging, sendToDevice, sendToMultipleDevices, sendToTopic, subscribeToTopic, unsubscribeFromTopic, getStatus };