# 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()