Clean env enforcement & add Gemini AI Post Generator

This commit is contained in:
Hamza-Ayed
2026-07-24 16:38:47 +03:00
parent 4621ede040
commit b2261d9192
5 changed files with 217 additions and 19 deletions
+11
View File
@@ -0,0 +1,11 @@
# Tripz — Meta & Marketing Environment Variables
# Copy this file to .env on your server and update as needed.
# Meta API Credentials
META_AD_ACCOUNT_ID=1945325153083644
META_PAGE_ID=1047354938453381
META_ACCESS_TOKEN=EAAM8GXpb76wBSCUHNxvd6PpSenb2HjkyyL8scTeocsmGRAk8kriqTqke85AVhQa36NExS0GC3DebnQJsgaXD01kh1oVbHZBRgpzI9RhtqZCmfyTonxwuD9cHngCkilrKiMVRh9YFbZBwWgBhiZB7THMYSIDJpOZAUXmcSjiBD1lvIcuM8HQ0oLkwq1ZBis063FiyQmPcy
# Gemini AI Credentials
GEMINI_API_KEY=AIzaSyDHp0yXCGWqnd4ynlCCWzDz9Un1EJOKeW8
GEMINI_MODEL=gemini-flash-lite-latest
+142
View File
@@ -0,0 +1,142 @@
#!/usr/bin/env node
/**
* Autonomous Gemini AI Post Generator & Facebook Publisher for Tripz
* Analyzes topic / prompt + marketing playbook rules and generates & publishes posts live!
*/
const fs = require('fs');
const path = require('path');
// Auto-load .env file if present
const envPath = path.resolve(__dirname, '../.env');
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, 'utf8');
envContent.split('\n').forEach(line => {
const match = line.match(/^\s*([\w.-]+)\s*=\s*(.*)\s*$/);
if (match) {
const key = match[1];
let value = match[2].trim().replace(/^['"]|['"]$/g, '');
if (!process.env[key]) process.env[key] = value;
}
});
}
const META_ACCESS_TOKEN = process.env.META_ACCESS_TOKEN;
const META_PAGE_ID = process.env.META_PAGE_ID;
const GEMINI_API_KEY = process.env.GEMINI_API_KEY;
const GEMINI_MODEL = process.env.GEMINI_MODEL || 'gemini-2.0-flash';
if (!META_ACCESS_TOKEN) {
console.error('ERROR: META_ACCESS_TOKEN is missing in .env environment file.');
process.exit(1);
}
if (!GEMINI_API_KEY) {
console.error('ERROR: GEMINI_API_KEY is missing in .env environment file.');
process.exit(1);
}
/**
* Generate Post Content using Gemini API
*/
async function generatePostWithGemini(topic = 'منشور تعريفي عن منصة Tripz ومزايا التملك والشفافية والتوفير') {
console.log(`Generating AI post content with Gemini (${GEMINI_MODEL}) for topic: "${topic}"...`);
const systemInstruction = `أنت مدير تسويق ومحرر إعلاني محترف لمنصة Tripz (منصة SaaS عالمية لإطلاق تطبيقات نقل الركاب وإدارة أساطيل التكسي بعلامة المشغّل التجارية).
قواعد التسويق الحاكمة (من docs/32):
1. الملكية: علامتك أنت، وتطبيقك باسمك وشعارك، وبياناتك تبقى لك بعقد تصدير مكتوب.
2. الشفافية: أسعارنا معلنة بالكامل دون أسرار ولا مفاجآت في الفاتورة.
3. السرعة: إطلاق خلال 30 يوماً من التوقيع على آبل وجوجل.
4. الإثبات: محرك مجرّب منذ 2019 يخدم أكثر من 6,000 سائق نشط.
5. دعوة للإجراء (CTA): رابط حاسبة التوفير (https://tripz-egypt.com/apps/) ورابط واتساب المباشر (https://wa.me/962798583052).
اكتب منشوراً جذاباً جداً باللغة العربية، منسقاً بالإيموجيات والعناوين والنقاط الواضحة والهاشتاغات المناسبة.`;
const url = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_API_KEY}`;
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
contents: [
{
role: 'user',
parts: [{ text: `${systemInstruction}\n\nالموضوع المطلوب كتابة منشور عنه:\n${topic}` }]
}
]
})
});
const data = await res.json();
if (data.error) {
throw new Error(`Gemini API Error: ${data.error.message}`);
}
const generatedText = data.candidates?.[0]?.content?.parts?.[0]?.text;
if (!generatedText) {
throw new Error('Gemini API returned an empty response.');
}
return generatedText.trim();
}
/**
* Publish generated post to Meta Facebook Page
*/
async function publishToFacebook(message) {
console.log('Publishing generated post to Facebook Page...');
const url = `https://graph.facebook.com/v19.0/me/feed`;
let res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
access_token: META_ACCESS_TOKEN,
message: message
})
});
let data = await res.json();
if (data.error && META_PAGE_ID) {
console.log('Direct /me/feed returned error, fallback to Page ID endpoint:', META_PAGE_ID);
const fallbackUrl = `https://graph.facebook.com/v19.0/${META_PAGE_ID}/feed`;
res = await fetch(fallbackUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
access_token: META_ACCESS_TOKEN,
message: message
})
});
data = await res.json();
}
if (data.error) {
throw new Error(`Meta Graph API Error [${data.error.code}]: ${data.error.message}`);
}
return data;
}
async function main() {
const topic = process.argv[2] || 'منشور تعريفي عن منصة Tripz ومزايا التملك والشفافية والتوفير وحاسبة الأرباح';
try {
const postContent = await generatePostWithGemini(topic);
console.log('\n--- Generated Post Content ---\n');
console.log(postContent);
console.log('\n------------------------------\n');
const result = await publishToFacebook(postContent);
console.log('🎉 Post Published Successfully to Facebook!');
console.log('Meta Post ID:', result.id);
} catch (err) {
console.error('❌ Error:', err.message);
}
}
if (require.main === module) {
main();
}
module.exports = { generatePostWithGemini, publishToFacebook };
+18 -7
View File
@@ -1,11 +1,22 @@
#!/usr/bin/env node
/**
* Meta Ads Automation Manager for Tripz
* Uses Meta Graph API v19.0
*/
const fs = require('fs');
const path = require('path');
const AD_ACCOUNT_ID = process.env.META_AD_ACCOUNT_ID || '1945325153083644';
const ACCESS_TOKEN = process.env.META_ACCESS_TOKEN || 'EAAM8GXpb76wBSP6SbqQ1ZAHCcmuPbk8J145t5ZBhVaQJByjEh3GzzpZAZApfVAf81lsiQPFK6oSlWwaZAbletLjQ2nEr1q8zNuNo0XQSbi31jf0VJEHwsW9ksosNlZBKP9KzPlgqt3wm7q5o1wmyUKFnnVu91d3z1b1CfKSSwQk1AfIo0HXZClt5eDL83C5G6ff7eH9CNy3oKUCQC9Wf239IJpYf2YbmvvXADoxKwvy0FTfMZCK0hPn4JMMkuGkqqQJDjDwSwEpszD3diCEGfWrN';
// Auto-load .env file if present
const envPath = path.resolve(__dirname, '../.env');
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, 'utf8');
envContent.split('\n').forEach(line => {
const match = line.match(/^\s*([\w.-]+)\s*=\s*(.*)\s*$/);
if (match) {
const key = match[1];
let value = match[2].trim().replace(/^['"]|['"]$/g, '');
if (!process.env[key]) process.env[key] = value;
}
});
}
const AD_ACCOUNT_ID = process.env.META_AD_ACCOUNT_ID;
const ACCESS_TOKEN = process.env.META_ACCESS_TOKEN;
const API_VERSION = 'v19.0';
const BASE_URL = `https://graph.facebook.com/${API_VERSION}`;
+23 -6
View File
@@ -1,10 +1,27 @@
#!/usr/bin/env node
/**
* Publish Post to Facebook Page via Meta Graph API v19.0
*/
const fs = require('fs');
const path = require('path');
const ACCESS_TOKEN = process.env.META_ACCESS_TOKEN || 'EAAM8GXpb76wBSP6SbqQ1ZAHCcmuPbk8J145t5ZBhVaQJByjEh3GzzpZAZApfVAf81lsiQPFK6oSlWwaZAbletLjQ2nEr1q8zNuNo0XQSbi31jf0VJEHwsW9ksosNlZBKP9KzPlgqt3wm7q5o1wmyUKFnnVu91d3z1b1CfKSSwQk1AfIo0HXZClt5eDL83C5G6ff7eH9CNy3oKUCQC9Wf239IJpYf2YbmvvXADoxKwvy0FTfMZCK0hPn4JMMkuGkqqQJDjDwSwEpszD3diCEGfWrN';
const PAGE_ID = process.env.META_PAGE_ID || '61588173848643';
// Auto-load .env file if present
const envPath = path.resolve(__dirname, '../.env');
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, 'utf8');
envContent.split('\n').forEach(line => {
const match = line.match(/^\s*([\w.-]+)\s*=\s*(.*)\s*$/);
if (match) {
const key = match[1];
let value = match[2].trim().replace(/^['"]|['"]$/g, '');
if (!process.env[key]) process.env[key] = value;
}
});
}
const ACCESS_TOKEN = process.env.META_ACCESS_TOKEN;
const PAGE_ID = process.env.META_PAGE_ID;
if (!ACCESS_TOKEN) {
console.error('ERROR: META_ACCESS_TOKEN is missing in .env file or environment variables.');
process.exit(1);
}
async function publishPost(message, imageUrl = null) {
if (!PAGE_ID) {
+23 -6
View File
@@ -1,10 +1,27 @@
#!/usr/bin/env node
/**
* Direct Live Publishing Script for Facebook Page
*/
const fs = require('fs');
const path = require('path');
const USER_TOKEN = process.env.META_ACCESS_TOKEN || 'EAAM8GXpb76wBSP6SbqQ1ZAHCcmuPbk8J145t5ZBhVaQJByjEh3GzzpZAZApfVAf81lsiQPFK6oSlWwaZAbletLjQ2nEr1q8zNuNo0XQSbi31jf0VJEHwsW9ksosNlZBKP9KzPlgqt3wm7q5o1wmyUKFnnVu91d3z1b1CfKSSwQk1AfIo0HXZClt5eDL83C5G6ff7eH9CNy3oKUCQC9Wf239IJpYf2YbmvvXADoxKwvy0FTfMZCK0hPn4JMMkuGkqqQJDjDwSwEpszD3diCEGfWrN';
const PAGE_ID = process.env.META_PAGE_ID || '1047354938453381';
// Auto-load .env file if present
const envPath = path.resolve(__dirname, '../.env');
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, 'utf8');
envContent.split('\n').forEach(line => {
const match = line.match(/^\s*([\w.-]+)\s*=\s*(.*)\s*$/);
if (match) {
const key = match[1];
let value = match[2].trim().replace(/^['"]|['"]$/g, '');
if (!process.env[key]) process.env[key] = value;
}
});
}
const USER_TOKEN = process.env.META_ACCESS_TOKEN;
const PAGE_ID = process.env.META_PAGE_ID;
if (!USER_TOKEN) {
console.error('ERROR: META_ACCESS_TOKEN is missing in .env file or environment variables.');
process.exit(1);
}
const message = `شركتك تحمل اسمك… وتطبيقك يحمل اسم غيرك؟ 🚘📱