| # from flask import Flask, request, jsonify | |
| # from flask_cors import CORS | |
| # import requests | |
| # import json | |
| # from datetime import datetime | |
| # from google.oauth2 import service_account | |
| # from googleapiclient.discovery import build | |
| # app = Flask(__name__) | |
| # CORS(app) | |
| # # ======================== | |
| # # CONFIGURATION | |
| # # ======================== | |
| # import os | |
| # from dotenv import load_dotenv | |
| # load_dotenv() | |
| # GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") | |
| # GOOGLE_CREDENTIALS_FILE = os.getenv("GOOGLE_CREDENTIALS_FILE") | |
| # SPREADSHEET_ID = os.getenv("SPREADSHEET_ID") | |
| # # ======================== | |
| # # GOOGLE SHEETS | |
| # # ======================== | |
| # def get_sheets_service(): | |
| # SCOPES = ['https://www.googleapis.com/auth/spreadsheets'] | |
| # creds = service_account.Credentials.from_service_account_file( | |
| # GOOGLE_CREDENTIALS_FILE, scopes=SCOPES) | |
| # service = build('sheets', 'v4', credentials=creds) | |
| # return service | |
| # def save_to_sheet(topic, caption, hashtags, reel_script, metadata): | |
| # try: | |
| # service = get_sheets_service() | |
| # sheet = service.spreadsheets() | |
| # timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
| # values = [[ | |
| # timestamp, | |
| # topic, | |
| # metadata.get('duration', 'N/A'), | |
| # metadata.get('level', 'N/A'), | |
| # metadata.get('tone', 'N/A'), | |
| # metadata.get('language', 'N/A'), | |
| # metadata.get('series_info', 'Single'), | |
| # caption, | |
| # hashtags, | |
| # reel_script | |
| # ]] | |
| # body = {'values': values} | |
| # sheet.values().append( | |
| # spreadsheetId=SPREADSHEET_ID, | |
| # range='Sheet1!A:J', | |
| # valueInputOption='RAW', | |
| # body=body | |
| # ).execute() | |
| # return True | |
| # except Exception as e: | |
| # print(f"Sheet Error: {e}") | |
| # return False | |
| # # ======================== | |
| # # GEMINI AI | |
| # # ======================== | |
| # def call_gemini_api(prompt, retry_count=0, max_retries=3): | |
| # import time | |
| # url = f"https://generativelanguage.googleapis.com/v1/models/gemini-2.5-flash:generateContent?key={GEMINI_API_KEY}" | |
| # headers = {"Content-Type": "application/json"} | |
| # data = { | |
| # "contents": [{ | |
| # "parts": [{"text": prompt}] | |
| # }] | |
| # } | |
| # # Progressive delay: 3s, 10s, 30s | |
| # delays = [3, 10, 30] | |
| # if retry_count > 0: | |
| # wait_time = delays[min(retry_count - 1, 2)] | |
| # print(f"⏳ Rate limit hit. Waiting {wait_time}s before retry {retry_count}/{max_retries}...") | |
| # time.sleep(wait_time) | |
| # else: | |
| # time.sleep(3) # Base delay between requests | |
| # response = requests.post(url, headers=headers, json=data) | |
| # if response.status_code == 200: | |
| # result = response.json() | |
| # return result['candidates'][0]['content']['parts'][0]['text'].strip() | |
| # elif response.status_code == 429: | |
| # if retry_count < max_retries: | |
| # return call_gemini_api(prompt, retry_count + 1, max_retries) | |
| # else: | |
| # raise Exception("Rate limit exceeded after retries. Please wait 1-2 minutes and try again!") | |
| # else: | |
| # raise Exception(f"API Error: {response.status_code}") | |
| # def generate_instagram_content(topic, duration, level, tone, language, series_config): | |
| # import time | |
| # # Tone descriptions | |
| # tone_styles = { | |
| # 'professional': 'professional and corporate tone', | |
| # 'funny': 'humorous, witty, and entertaining tone with jokes', | |
| # 'inspiring': 'motivational, uplifting, and inspiring tone', | |
| # 'serious': 'serious, educational, and informative tone', | |
| # 'casual': 'casual, friendly, and conversational tone', | |
| # 'storytelling': 'narrative storytelling style with engaging flow' | |
| # } | |
| # # Language instructions | |
| # language_styles = { | |
| # 'hinglish': 'Mix of Hindi and English (Hinglish). Use both languages naturally', | |
| # 'hindi': 'Pure Hindi language only. No English words', | |
| # 'english': 'Pure English language only. No Hindi words' | |
| # } | |
| # # Content level descriptions | |
| # level_descriptions = { | |
| # 'basic': 'simple, easy-to-understand for beginners', | |
| # 'intermediate': 'moderate depth with some technical terms', | |
| # 'advanced': 'in-depth, expert-level with advanced concepts' | |
| # } | |
| # tone_desc = tone_styles.get(tone, 'inspiring tone') | |
| # lang_desc = language_styles.get(language, 'Hinglish') | |
| # level_desc = level_descriptions.get(level, 'intermediate') | |
| # # Calculate scenes | |
| # scenes = calculate_scenes(duration) | |
| # # Series context | |
| # series_context = "" | |
| # if series_config['enabled']: | |
| # current = series_config['currentPart'] | |
| # total = series_config['totalParts'] | |
| # previous = series_config.get('previousContent', '') | |
| # if current == 1: | |
| # series_context = f"\n\nSERIES INFO: This is PART 1/{total} of a series. End with a hook/cliffhanger for next part!" | |
| # elif current == total: | |
| # series_context = f"\n\nSERIES INFO: FINAL PART {current}/{total}. Provide conclusion referencing previous parts.\nPrevious: {previous[:400]}" | |
| # else: | |
| # series_context = f"\n\nSERIES INFO: PART {current}/{total}. Continue from previous part.\nPrevious: {previous[:400]}" | |
| # # CAPTION | |
| # caption_prompt = f"""Create Instagram caption for: {topic} | |
| # REQUIREMENTS: | |
| # - Tone: {tone_desc} | |
| # - Language: {lang_desc} | |
| # - Level: {level_desc} | |
| # - 2-3 lines, engaging | |
| # - Use emojis | |
| # - Call-to-action | |
| # {f'- Mention Part {series_config["currentPart"]}/{series_config["totalParts"]}' if series_config['enabled'] else ''} | |
| # ONLY return caption, nothing else.""" | |
| # print(f"Generating caption: {topic}") | |
| # caption = call_gemini_api(caption_prompt) | |
| # # HASHTAGS | |
| # hashtags_prompt = f"""Generate 12-15 Instagram hashtags for: {topic} | |
| # Style: {tone} | |
| # Language: {language} | |
| # Level: {level} | |
| # Return ONLY hashtags with # in one line.""" | |
| # print("Generating hashtags...") | |
| # hashtags = call_gemini_api(hashtags_prompt) | |
| # # REEL SCRIPT | |
| # reel_prompt = f"""Create {duration}-second Instagram Reel script for: {topic} | |
| # STYLE: | |
| # - Tone: {tone_desc} | |
| # - Language: {lang_desc} | |
| # - Level: {level_desc} | |
| # STRUCTURE ({scenes['total_duration']} seconds total): | |
| # [Hook] - Opening (2-3s) | |
| # {chr(10).join([f'[Scene {i+1}] - Description ({scenes["scene_duration"]}s)' for i in range(scenes["num_scenes"])])} | |
| # [CTA] - Call to action (3-5s) | |
| # {series_context} | |
| # FORMAT EXACTLY as shown above. Make it viral!""" | |
| # print("Generating reel script...") | |
| # reel_script = call_gemini_api(reel_prompt) | |
| # return caption, hashtags, reel_script | |
| # def calculate_scenes(duration): | |
| # available_time = duration - 8 | |
| # if duration <= 20: | |
| # num_scenes = 2 | |
| # elif duration <= 45: | |
| # num_scenes = 3 | |
| # elif duration <= 75: | |
| # num_scenes = 4 | |
| # elif duration <= 120: | |
| # num_scenes = 5 | |
| # else: | |
| # num_scenes = 6 | |
| # scene_duration = available_time // num_scenes | |
| # return { | |
| # 'num_scenes': num_scenes, | |
| # 'scene_duration': scene_duration, | |
| # 'total_duration': duration | |
| # } | |
| # # ======================== | |
| # # API ROUTES | |
| # # ======================== | |
| # @app.route('/') | |
| # def home(): | |
| # return """ | |
| # 🎨 Instagram AI Content Generator ULTIMATE | |
| # ⚡ Powered by Sai Tech | |
| # Features: | |
| # - Bulk content generation | |
| # - Custom tone, language, level | |
| # - Multi-part series | |
| # - PDF/ZIP export | |
| # Status: Running ✅ | |
| # """ | |
| # @app.route('/generate', methods=['POST']) | |
| # def generate(): | |
| # try: | |
| # data = request.json | |
| # topic = data.get('topic', '').strip() | |
| # duration = data.get('duration', 30) | |
| # level = data.get('level', 'intermediate') | |
| # tone = data.get('tone', 'inspiring') | |
| # language = data.get('language', 'hinglish') | |
| # series_config = data.get('series', {'enabled': False}) | |
| # if not topic: | |
| # return jsonify({ | |
| # 'success': False, | |
| # 'error': 'Topic required!' | |
| # }), 400 | |
| # print(f"\n{'='*60}") | |
| # print(f"⚡ SAI TECH - Processing Request") | |
| # print(f"{'='*60}") | |
| # print(f" Topic: {topic}") | |
| # print(f" Duration: {duration}s") | |
| # print(f" Level: {level}") | |
| # print(f" Tone: {tone}") | |
| # print(f" Language: {language}") | |
| # if series_config['enabled']: | |
| # print(f" Series: Part {series_config['currentPart']}/{series_config['totalParts']}") | |
| # print(f"{'='*60}\n") | |
| # # Generate content | |
| # caption, hashtags, reel_script = generate_instagram_content( | |
| # topic, duration, level, tone, language, series_config | |
| # ) | |
| # # Metadata | |
| # metadata = { | |
| # 'duration': f"{duration}s", | |
| # 'level': level, | |
| # 'tone': tone, | |
| # 'language': language, | |
| # 'series_info': f"Part {series_config['currentPart']}/{series_config['totalParts']}" if series_config['enabled'] else "Single" | |
| # } | |
| # # Save to sheets | |
| # save_to_sheet(topic, caption, hashtags, reel_script, metadata) | |
| # print("✅ Content generated successfully!\n") | |
| # return jsonify({ | |
| # 'success': True, | |
| # 'topic': topic, | |
| # 'caption': caption, | |
| # 'hashtags': hashtags, | |
| # 'reel_script': reel_script, | |
| # 'metadata': metadata | |
| # }) | |
| # except Exception as e: | |
| # print(f"\n❌ Error: {str(e)}\n") | |
| # return jsonify({ | |
| # 'success': False, | |
| # 'error': str(e) | |
| # }), 500 | |
| # if __name__ == '__main__': | |
| # print("=" * 70) | |
| # print("⚡ SAI TECH - Instagram AI Content Generator ULTIMATE") | |
| # print("=" * 70) | |
| # print("📍 Server: http://localhost:5000") | |
| # print("🌐 Open index.html in browser") | |
| # print("=" * 70) | |
| # print("\n🔥 ULTIMATE Features:") | |
| # print(" ✅ Bulk topic generation") | |
| # print(" ✅ Custom tone (Professional/Funny/Inspiring/etc)") | |
| # print(" ✅ Language selection (Hindi/English/Hinglish)") | |
| # print(" ✅ Content levels (Basic/Intermediate/Advanced)") | |
| # print(" ✅ Multi-part series with auto-continuation") | |
| # print(" ✅ PDF/ZIP download with Sai Tech watermark") | |
| # print(" ✅ Auto Google Sheets backup") | |
| # print("=" * 70) | |
| # print("\n💡 Example Bulk Topics:") | |
| # print(" motivation, fitness, cooking, travel, photography") | |
| # print("=" * 70) | |
| # app.run(debug=True, port=5000) | |
| # from flask import Flask, request, jsonify | |
| # from flask_cors import CORS | |
| # import requests | |
| # import json | |
| # import time | |
| # import os | |
| # from datetime import datetime | |
| # from dotenv import load_dotenv | |
| # from google.oauth2 import service_account | |
| # from googleapiclient.discovery import build | |
| # app = Flask(__name__) | |
| # CORS(app) | |
| # load_dotenv() | |
| # GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") | |
| # GOOGLE_CREDENTIALS_FILE = os.getenv("GOOGLE_CREDENTIALS_FILE") | |
| # SPREADSHEET_ID = os.getenv("SPREADSHEET_ID") | |
| # CACHE = {} | |
| # LAST_CALL_TIME = 0 | |
| # MIN_INTERVAL = 2 | |
| # def get_sheets_service(): | |
| # SCOPES = ['https://www.googleapis.com/auth/spreadsheets'] | |
| # creds = service_account.Credentials.from_service_account_file( | |
| # GOOGLE_CREDENTIALS_FILE, scopes=SCOPES | |
| # ) | |
| # return build('sheets', 'v4', credentials=creds) | |
| # def save_to_sheet(topic, caption, hashtags, reel_script, metadata): | |
| # try: | |
| # service = get_sheets_service() | |
| # sheet = service.spreadsheets() | |
| # timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
| # values = [[ | |
| # timestamp, topic, | |
| # metadata.get("duration"), | |
| # metadata.get("level"), | |
| # metadata.get("tone"), | |
| # metadata.get("language"), | |
| # metadata.get("series_info"), | |
| # caption, hashtags, reel_script | |
| # ]] | |
| # sheet.values().append( | |
| # spreadsheetId=SPREADSHEET_ID, | |
| # range="Sheet1!A:J", | |
| # valueInputOption="RAW", | |
| # body={"values": values} | |
| # ).execute() | |
| # return True | |
| # except Exception as e: | |
| # print("Sheet Error:", e) | |
| # return False | |
| # def call_gemini_api(prompt, retry=0): | |
| # global LAST_CALL_TIME | |
| # if prompt in CACHE: | |
| # return CACHE[prompt] | |
| # now = time.time() | |
| # wait = MIN_INTERVAL - (now - LAST_CALL_TIME) | |
| # if wait > 0: | |
| # time.sleep(wait) | |
| # url = f"https://generativelanguage.googleapis.com/v1/models/gemini-2.5-flash:generateContent?key={GEMINI_API_KEY}" | |
| # headers = {"Content-Type": "application/json"} | |
| # data = {"contents": [{"parts": [{"text": prompt}]}]} | |
| # response = requests.post(url, headers=headers, json=data) | |
| # LAST_CALL_TIME = time.time() | |
| # if response.status_code == 200: | |
| # text = response.json()["candidates"][0]["content"]["parts"][0]["text"].strip() | |
| # CACHE[prompt] = text | |
| # return text | |
| # if response.status_code == 429 and retry < 3: | |
| # time.sleep(5 * (retry + 1)) | |
| # return call_gemini_api(prompt, retry + 1) | |
| # raise Exception(f"Gemini API Error: {response.status_code}") | |
| # def generate_instagram_content(topic, duration, level, tone, language, series): | |
| # series_context = "" | |
| # if series.get("enabled"): | |
| # current = series.get("currentPart", 1) | |
| # total = series.get("totalParts", 1) | |
| # prev = series.get("previousContent", "")[:300] | |
| # if current == 1: | |
| # series_context = f"PART 1/{total}. End with hook." | |
| # elif current == total: | |
| # series_context = f"FINAL PART {current}/{total}. Previous: {prev}" | |
| # else: | |
| # series_context = f"PART {current}/{total}. Continue. Previous: {prev}" | |
| # prompt = f''' | |
| # Create Instagram content for topic: {topic} | |
| # Return ONLY valid JSON: | |
| # {{ | |
| # "caption": "...", | |
| # "hashtags": "...", | |
| # "reel_script": "..." | |
| # }} | |
| # Tone: {tone} | |
| # Language: {language} | |
| # Level: {level} | |
| # Duration: {duration}s | |
| # {series_context} | |
| # ''' | |
| # response = call_gemini_api(prompt) | |
| # try: | |
| # data = json.loads(response) | |
| # return data["caption"], data["hashtags"], data["reel_script"] | |
| # except Exception: | |
| # raise Exception("Invalid JSON from AI") | |
| # @app.route("/") | |
| # def home(): | |
| # return "Sai Tech AI Generator Running 🚀" | |
| # @app.route("/generate", methods=["POST"]) | |
| # def generate(): | |
| # try: | |
| # data = request.json | |
| # topic = data.get("topic", "").strip() | |
| # duration = data.get("duration", 30) | |
| # level = data.get("level", "intermediate") | |
| # tone = data.get("tone", "inspiring") | |
| # language = data.get("language", "hinglish") | |
| # series = data.get("series", {"enabled": False}) | |
| # if not topic: | |
| # return jsonify({"success": False, "error": "Topic required"}), 400 | |
| # caption, hashtags, reel_script = generate_instagram_content( | |
| # topic, duration, level, tone, language, series | |
| # ) | |
| # metadata = { | |
| # "duration": f"{duration}s", | |
| # "level": level, | |
| # "tone": tone, | |
| # "language": language, | |
| # "series_info": f"Part {series.get('currentPart',1)}/{series.get('totalParts',1)}" | |
| # } | |
| # save_to_sheet(topic, caption, hashtags, reel_script, metadata) | |
| # return jsonify({ | |
| # "success": True, | |
| # "caption": caption, | |
| # "hashtags": hashtags, | |
| # "reel_script": reel_script | |
| # }) | |
| # except Exception as e: | |
| # return jsonify({"success": False, "error": str(e)}), 500 | |
| # if __name__ == "__main__": | |
| # app.run(debug=True, port=5000) | |
| import os | |
| import time | |
| import requests | |
| import gradio as gr | |
| from datetime import datetime | |
| from google.oauth2 import service_account | |
| from googleapiclient.discovery import build | |
| # ======================== | |
| # ENV VARIABLES | |
| # ======================== | |
| GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") | |
| GOOGLE_CREDENTIALS_FILE = os.getenv("GOOGLE_CREDENTIALS_FILE") | |
| SPREADSHEET_ID = os.getenv("SPREADSHEET_ID") | |
| # ======================== | |
| # GOOGLE SHEETS | |
| # ======================== | |
| def get_sheets_service(): | |
| SCOPES = ['https://www.googleapis.com/auth/spreadsheets'] | |
| creds = service_account.Credentials.from_service_account_file( | |
| GOOGLE_CREDENTIALS_FILE, scopes=SCOPES) | |
| return build('sheets', 'v4', credentials=creds) | |
| def save_to_sheet(topic, caption, hashtags, reel_script, metadata): | |
| try: | |
| service = get_sheets_service() | |
| sheet = service.spreadsheets() | |
| timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
| values = [[ | |
| timestamp, | |
| topic, | |
| metadata.get('duration'), | |
| metadata.get('level'), | |
| metadata.get('tone'), | |
| metadata.get('language'), | |
| metadata.get('series_info'), | |
| caption, | |
| hashtags, | |
| reel_script | |
| ]] | |
| sheet.values().append( | |
| spreadsheetId=SPREADSHEET_ID, | |
| range='Sheet1!A:J', | |
| valueInputOption='RAW', | |
| body={'values': values} | |
| ).execute() | |
| except Exception as e: | |
| print("Sheet Error:", e) | |
| # ======================== | |
| # GEMINI CALL | |
| # ======================== | |
| def call_gemini(prompt): | |
| url = f"https://generativelanguage.googleapis.com/v1/models/gemini-2.5-flash:generateContent?key={GEMINI_API_KEY}" | |
| data = { | |
| "contents": [{"parts": [{"text": prompt}]}] | |
| } | |
| time.sleep(2) | |
| res = requests.post(url, json=data) | |
| if res.status_code != 200: | |
| raise Exception(f"Gemini Error: {res.status_code}") | |
| return res.json()['candidates'][0]['content']['parts'][0]['text'].strip() | |
| # ======================== | |
| # MAIN GENERATOR | |
| # ======================== | |
| def generate_content(topic, duration, level, tone, language): | |
| caption = call_gemini(f"Write short Instagram caption about {topic} in {language} with {tone} tone.") | |
| hashtags = call_gemini(f"Give 15 hashtags for {topic}.") | |
| reel = call_gemini(f"Write {duration} sec Instagram reel script about {topic}.") | |
| metadata = { | |
| "duration": f"{duration}s", | |
| "level": level, | |
| "tone": tone, | |
| "language": language, | |
| "series_info": "Single" | |
| } | |
| save_to_sheet(topic, caption, hashtags, reel, metadata) | |
| return caption, hashtags, reel | |
| # ======================== | |
| # GRADIO UI | |
| # ======================== | |
| with gr.Blocks(title="Instagram AI Generator") as app: | |
| gr.Markdown("# 🚀 Instagram AI Content Generator") | |
| gr.Markdown("Generate captions, hashtags & reel scripts using AI") | |
| topic = gr.Textbox(label="Topic") | |
| duration = gr.Slider(10, 120, value=30, step=5, label="Reel Duration (sec)") | |
| level = gr.Dropdown(["basic", "intermediate", "advanced"], value="intermediate", label="Level") | |
| tone = gr.Dropdown(["professional", "funny", "inspiring", "casual"], value="inspiring", label="Tone") | |
| language = gr.Dropdown(["english", "hindi", "hinglish"], value="hinglish", label="Language") | |
| btn = gr.Button("Generate") | |
| caption_out = gr.Textbox(label="Caption") | |
| hashtag_out = gr.Textbox(label="Hashtags") | |
| reel_out = gr.Textbox(label="Reel Script", lines=8) | |
| btn.click( | |
| generate_content, | |
| inputs=[topic, duration, level, tone, language], | |
| outputs=[caption_out, hashtag_out, reel_out] | |
| ) | |
| app.launch() | |