Spaces:
Running
Running
| import gradio as gr | |
| from google import genai | |
| import json | |
| import os | |
| from datetime import datetime, timedelta | |
| # ๐ แกแแปแแบแกแแแบแแปแฌแธแแญแฏ แกแแฑแแพแแบแแฌแธแแแทแบ JSON Database แแญแฏแแบแกแแแบ | |
| DB_FILE = "recap_users_db.json" | |
| # ๐ แ แแแบแกแแฏแถแธแแผแฏแแปแญแแบแแฝแแบ แแซแแแบแแแทแบ แกแแผแฑแแถ แกแแฑแฌแแทแบแแปแฌแธ | |
| DEFAULT_DB = { | |
| "admin": { | |
| "password": "241212", # ๐ Admin แกแแฝแแบ Password | |
| "role": "admin" | |
| }, | |
| "user1": { | |
| "password": "456456", # ๐ Free User แกแแฝแแบ Password | |
| "role": "free", | |
| "last_used_date": "", | |
| "usage_count": 0 | |
| } | |
| } | |
| # ๐ Database แแแบแแแทแบ แ แแ แบ | |
| def load_db(): | |
| if not os.path.exists(DB_FILE): | |
| with open(DB_FILE, "w", encoding="utf-8") as f: | |
| json.dump(DEFAULT_DB, f, indent=4, ensure_ascii=False) | |
| return DEFAULT_DB | |
| try: | |
| with open(DB_FILE, "r", encoding="utf-8") as f: | |
| return json.load(f) | |
| except: | |
| return DEFAULT_DB | |
| # ๐พ Database แแญแแบแธแแแบแธแแแทแบ แ แแ แบ | |
| def save_db(db_data): | |
| with open(DB_FILE, "w", encoding="utf-8") as f: | |
| json.dump(db_data, f, indent=4, ensure_ascii=False) | |
| # ๐ Login แ แ แบแแฑแธแแฑแธแแแทแบ Function | |
| def check_login(username, password): | |
| username = username.strip() | |
| password = password.strip() | |
| db = load_db() | |
| if username in db and db[username]["password"] == password: | |
| user_info = db[username] | |
| role = user_info["role"] | |
| if role == "member": | |
| expiry = datetime.strptime(user_info["expiry_date"], "%Y-%m-%d") | |
| if datetime.now() > expiry: | |
| return gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), f"๐ซ แกแแฏแถแธแแผแฏแแฐ '{username}' แแแบ แแแบแแแบแธแแฏแแบแแฏแถแธแแฝแฌแธแแซแแผแฎแ" | |
| role_text = f"โญ PAID MEMBER (แแแบแแแบแธแแฏแแบแแแบ - {user_info['expiry_date']})" | |
| return gr.update(visible=False), gr.update(visible=True), gr.update(visible=False), f"โ แกแฑแฌแแบแแผแแบแ แฝแฌ แแแบแแฑแฌแแบแแผแฎแธแแซแแผแฎแ [{role_text}]" | |
| elif role == "admin": | |
| return gr.update(visible=False), gr.update(visible=True), gr.update(visible=True), "๐ แแแบแนแแแฌแแซ ADMIN แแผแฎแธแแปแฌแ แ แแ แบแแ แบแแฏแแฏแถแธแแญแฏ แ แฎแแถแแแทแบแแฝแฒแแญแฏแแบแแซแแผแฎแ" | |
| elif role == "free": | |
| return gr.update(visible=False), gr.update(visible=True), gr.update(visible=False), "๐ FREE USER แกแแผแ แบ แกแฑแฌแแบแแผแแบแ แฝแฌ แแแบแแฑแฌแแบแแผแฎแธแแซแแผแฎแ (แแ แบแแฑแท แ แแผแญแแบ แแแทแบแแแบแแปแแบแแพแญ)" | |
| return gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), "โ Username แแญแฏแทแแแฏแแบ Password แแพแฌแธแแฝแแบแธแแฑแแซแแแบแ" | |
| # ===================================================================== | |
| # ๐ MAIN RECAP PROCESSOR (With Security & Usage Limit) | |
| # ===================================================================== | |
| def process_movie_recap(logged_in_user, movie_name, episode_part, movie_context, api_key, duration_choice, progress=gr.Progress(track_tqdm=True)): | |
| if not logged_in_user: | |
| return "๐ แแปแฑแธแแฐแธแแผแฏแ แ แแ แบแกแแฝแแบแธแแญแฏแท แกแแแบ Login แแแบแแฑแธแแซแ" | |
| if not api_key or api_key.strip() == "": | |
| return "โ ๏ธ แแปแฑแธแแฐแธแแผแฏแ แแแบแ Gemini API Key แแญแฏ แกแแแบแแแทแบแแฑแธแแซแแปแฌเฅค" | |
| if not movie_name or movie_name.strip() == "": | |
| return "โ ๏ธ แแปแฑแธแแฐแธแแผแฏแ แแฏแแบแแพแแบ แแญแฏแทแแแฏแแบ แ แฎแธแแฎแธแแฌแแแบแแญแฏ แแแทแบแแฝแแบแธแแฑแธแแซแแปแฌเฅค" | |
| db = load_db() | |
| if logged_in_user not in db: | |
| return "โ แกแแฏแถแธแแผแฏแแฐ แแแพแญแแฑแฌแทแแซแ" | |
| user_info = db[logged_in_user] | |
| today_str = datetime.now().strftime("%Y-%m-%d") | |
| # ๐ก๏ธ Limit แ แ แบแแฑแธแแผแแบแธแ แแ แบ (Free & Member) | |
| if user_info["role"] != "admin": | |
| if user_info.get("last_used_date") == today_str and user_info.get("usage_count", 0) >= 1: | |
| return "๐ซ แแแบแแแบ แแแฑแทแกแแฝแแบ แแผแฏแแฏแแบแแฝแแทแบ (แ) แแผแญแแบ แแผแแทแบแแฝแฌแธแแซแแผแฎแ แแฑแฌแแบแแฑแทแแพ แแผแแบแแแบ แ แแบแธแแแบแแซแแแบแ" | |
| if duration_choice == "Short (TikTok/Reels - 1 Min)": | |
| word_count = "แ แฌแแฏแถแธแแฑ แแแ แแปแฑแฌแบ แแพ แ แแ แกแแฝแแบแธ" | |
| length_desc = "แ แแญแแ แบแ แฌ Short แแฎแแฎแแญแฏ" | |
| elif duration_choice == "Medium (YouTube - 3 to 5 Mins)": | |
| word_count = "แ แฌแแฏแถแธแแฑ แแ ้งแฌแบ แแพ แแแแ แกแแฝแแบแธ" | |
| length_desc = "แ แแญแแ แบแแพ แ แแญแแ แบแ แฌ YouTube แแฎแแฎแแญแฏ" | |
| else: | |
| word_count = "แ แฌแแฏแถแธแแฑ แแแ0 แแปแฑแฌแบ แแพ แแแแ แกแแฝแแบแธ" | |
| length_desc = "แแ แแญแแ แบแ แฌ YouTube Long-form แแฎแแฎแแญแฏ" | |
| additional_context = "" | |
| if movie_context and movie_context.strip() != "": | |
| additional_context = f"\n[แคแแฏแแบแแพแแบแ แ แ แบแแพแแบแแฑแฌ แแฌแแบแแแบแธ Context แกแแปแแบแกแแแบแแปแฌแธ -\n{movie_context.strip()}]\n" | |
| try: | |
| client = genai.Client(api_key=api_key.strip()) | |
| movie_info = f"แแฏแแบแแพแแบ/แ แฎแธแแฎแธ แแฌแแแบแแผแ แบแแแทแบ '{movie_name.strip()}' แแญแฏ แกแแผแฑแแถแแซแ " | |
| episode_info = f"แกแแฐแธแแแผแแทแบ '{episode_part.strip()}' แ แแฌแแบแแแบแธแแ แบแแฏแแฏแถแธแแญแฏ " if episode_part and episode_part.strip() else "แแฌแแบแแแบแธแแ แบแแฏแแฏแถแธแแญแฏ " | |
| progress(0.50, desc="โก Gemini AI แแแฑ แแฌแแบแแแบแธแแญแฏ แกแ แกแแฏแถแธ แแฑแซแแบแธแ แแบแแผแฎแธ แแฑแธแแฌแธแแฑแแซแแแบ...") | |
| script_prompt = ( | |
| f"แแแบแธแ แแฏแแบแแพแแบแแพแแทแบ แ แฎแธแแฎแธแแปแฌแธแแญแฏ Recap แแฏแแบแแฒแท Professional Content Creator แแ แบแแฑแฌแแบ แแผแ แบแแแบแ " | |
| f"{movie_info} {episode_info} " | |
| f"แแ แบแแแบแแ แบแแปแแบแแพแแทแบ แแผแแบแแแปแแฌแธแแฒแ แกแ -แกแแแบ-แกแแฏแถแธ แแฌแแบแแญแแบแธแแญแฏแแบแธแกแแญ (แแญแฏ Episode แแญแฏแทแแแฏแแบ แแฌแแบแแฌแธแ แแฌแแบแแญแแบแธแแแบแธแกแแญ) แแผแฎแธแแผแแทแบแ แฏแถแ แฝแฌ แแซแแแบแแฑแฌ {length_desc} แกแแฝแแบ แแผแแบแแฌแแญแฏ Video Recap Script แแ แบแแฏแแญแฏ แแฑแธแแฑแธแแซแ" | |
| f"{additional_context}\n\n" | |
| f"แแแบแแพแแบแแปแแบแแปแฌแธ (แแแผแ แบแแแฑแแญแฏแแบแแฌแแแบ) -\n" | |
| f"แแ โ ๏ธ แกแแฑแธแแผแฎแธแแฏแถแธแกแแปแแบ - แแฑแธแแฌแธแแฑแฌ แกแแญแฏแแบแธ (Episode) แแญแฏแทแแแฏแแบ แแฌแแบแแแบแธแแฝแฒแ แแฌแแบแแฝแแบ แกแ แแพ แกแแฏแถแธแแญ 'แแฌแแบแแญแแบแธแแญแฏแแบแธ (Ending)' แแญแฏ แแแผแ แบแแแฑ แแแทแบแแฝแแบแธแแแแบแ แแแบแธแแ แบแแแบแแฝแแบ แ แฌแแฌแธแแผแแบแแฑแฌแแบแแผแฎแธ แแแญแแแบแแญแฏ แแปแพแฑแฌแบแแญแฏแแบแธแแฌแธแแผแแบแธแแปแญแฏแธ แแฏแถแธแ (แแฏแถแธแ) แแแฏแแบแแแซแ แแ แบแแฏแแบแแฏแถแธ แกแแผแฎแธแแแบแแฑแธแแแแบแ\n" | |
| f"แแ แ แแฌแธแแผแฑแฌแแแบแ แแแญแแแบแแญแฏ แแฝแฒแแฑแฌแแบแแพแฏแแพแญแแผแฎแธ แแฌแแบแแพแญแแบแแแบแกแฑแฌแแบ แ แญแแบแแพแฏแแบแแพแฌแธแ แแฌ แกแแผแแทแบแแผแ แบแแแแบแ แ แฌแกแฏแแบแแแบแแผแแแญแฏแแปแญแฏแธ แแฏแถแธแ แแแฏแแบแแซแแฒแทแ\n" | |
| f"แแ แแซแ {length_desc} แแผแ แบแแญแฏแท แแผแแบแแฌแ แฌแแฌแธแแญแฏ {word_count} แกแแผแแทแบแกแ แฏแถ แแปแแฑแธแแฑแธแแซแ แ แฌแแฏแถแธแแฑ แแแทแบแแแบแแปแแบแกแแฝแแบแธแแพแฌแแฒ แแฌแแบแแแบแธแแ แบแแฏแแฏแถแธ แแผแฎแธแแฏแถแธแแฝแฌแธแกแฑแฌแแบ แกแแปแญแแบแกแ แแแบแแญแฏแแบแแแปแพ แแปแพแแผแฎแธ แแฑแธแแฑแธแแซแ\n" | |
| f"แแ Creator Tips แแฝแฑแ แแฌแแบแแฝแแบแแฑแฌแบแแผแแปแแบแแฝแฑ (แฅแแแฌ- Visual: ...) แแฏแถแธแ แแแทแบแแแฑแธแแซแแฒแทแ แแฑแฌแแบแแถแ แแฌแธแแผแฑแฌ (Voiceover) แกแแฝแแบ แแผแแบแแฌแแญแฏ แ แแฌแธแแผแฑแฌแ แฌแแฌแธ แแฎแธแแแทแบแแญแฏแแฒ แแปแแฑแธแแฑแธแแแซแแแบเฅค" | |
| ) | |
| response = client.models.generate_content(model='gemini-2.5-flash', contents=script_prompt) | |
| burmese_script = response.text | |
| # ๐พ แกแฑแฌแแบแแผแแบแแซแ Usage Count แแพแแบแแฌแธแแแบ | |
| if user_info["role"] != "admin": | |
| user_info["last_used_date"] = today_str | |
| user_info["usage_count"] = 1 | |
| db[logged_in_user] = user_info | |
| save_db(db) | |
| return burmese_script | |
| except Exception as e: | |
| return f"โ Error แแแบแแฝแฌแธแแซแแแบ- {str(e)}" | |
| # ๐ [ADMIN FEATURE]: Member แแ แบแแแทแบแแผแแบแธ | |
| def admin_add_member(new_username, new_password): | |
| new_username = new_username.strip() | |
| new_password = new_password.strip() | |
| if not new_username or not new_password: | |
| return "โ Username แแพแแทแบ Password แกแฌแธแแฏแถแธ แแญแฏแแบแแแทแบแแฑแธแแซแ", get_members_table() | |
| db = load_db() | |
| if new_username in db: | |
| return f"โ แกแแฏแถแธแแผแฏแแฐแแฌแแแบ '{new_username}' แแแบ แแพแญแแพแแทแบแแผแฎแธแแฌแธ แแผแ แบแแฑแแแบแ", get_members_table() | |
| expiry_date = (datetime.now() + timedelta(days=30)).strftime("%Y-%m-%d") | |
| db[new_username] = { | |
| "password": new_password, | |
| "role": "member", | |
| "expiry_date": expiry_date, | |
| "last_used_date": "", | |
| "usage_count": 0 | |
| } | |
| save_db(db) | |
| return f"โ Paid Member '{new_username}' แกแฌแธ (แ) แ แแแบแแแบแธแแผแแทแบ แกแฑแฌแแบแแผแแบแ แฝแฌ แแแบแแฑแฌแแบแแผแฎแธแแซแแผแฎแ", get_members_table() | |
| # ๐ [ADMIN FEATURE]: Member แกแฌแธ แแผแแบแแปแแบแแผแแบแธ แแแฏแแบ | |
| def admin_delete_member(username_to_delete): | |
| username_to_delete = username_to_delete.strip() | |
| if not username_to_delete: | |
| return "โ แแปแฑแธแแฐแธแแผแฏแ แแปแแบแแญแฏแแฑแฌ Username แแญแฏ แแญแฏแแบแแแทแบแแซแ", get_members_table() | |
| db = load_db() | |
| if username_to_delete in db: | |
| if db[username_to_delete]["role"] == "member": | |
| del db[username_to_delete] | |
| save_db(db) | |
| return f"๐๏ธ Paid Member '{username_to_delete}' แกแฌแธ แ แแ แบแแฒแแพ แกแแผแฎแธแแปแแบแแญแฏแแบแแซแแผแฎแ", get_members_table() | |
| else: | |
| return "โ Admin แแญแฏแทแแแฏแแบ Free User แกแแฑแฌแแทแบแแญแฏ แแปแแบแแแแแซแ", get_members_table() | |
| return f"โ แกแแฏแถแธแแผแฏแแฐ '{username_to_delete}' แแญแฏ แแพแฌแแแฝแฑแทแแซแ", get_members_table() | |
| # ๐ [ADMIN FEATURE]: Member แแแฌแธแแฏแแบแแฑแธแแผแแบแธ | |
| def get_members_table(): | |
| db = load_db() | |
| table_data = [] | |
| for user, data in db.items(): | |
| if data["role"] == "member": | |
| table_data.append([user, data["password"], data["expiry_date"], data.get("last_used_date", "แแแพแญแแฑแธ"), "แแผแแทแบ" if data.get("usage_count",0)>=1 else "แแปแแบ"]) | |
| return table_data | |
| # ===================================================================== | |
| # ๐จ GRADIO UI DESIGN WITH SECURITY SYSTEM | |
| # ===================================================================== | |
| with gr.Blocks(title="Smart Movie Auto Recap Pro") as demo: | |
| current_logged_user = gr.State(value="") | |
| gr.Markdown("# โจ Smart Movie Auto Recap Pro (v 2.0) โจ") | |
| gr.Markdown("๐ก๏ธ Secure Account Control & Professional Script Generator") | |
| status_output = gr.Textbox(label="โน๏ธ Login Status", value="๐ แแปแฑแธแแฐแธแแผแฏแ แ แแ แบแกแแฝแแบแธแแญแฏแท แกแแแบแแแบแแฑแฌแแบแแฑแธแแซแ", interactive=False) | |
| # 1. ๐ LOGIN BOX | |
| with gr.Group() as login_box: | |
| gr.Markdown("### ๐ แกแแฑแฌแแทแบแแแบแแแบ") | |
| username_input = gr.Textbox(label="Username", placeholder="๐ค Username แแญแฏแแบแแแทแบแแซ") | |
| password_input = gr.Textbox(label="Password", placeholder="๐ Password แแญแฏแแบแแแทแบแแซ", type="password") | |
| login_btn = gr.Button("Login แแแบแแแบ", variant="primary") | |
| # 2. ๐ ADMIN CONTROL PANEL | |
| with gr.Group(visible=False) as admin_panel: | |
| gr.Markdown("## ๐ Admin Control Panel (Member Management)") | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("### โ Member แกแแ แบ แแแทแบแแแบ") | |
| new_user_in = gr.Textbox(label="Member แแ แบแ Username", placeholder="แฅแแแฌ - member_mgmg") | |
| new_pass_in = gr.Textbox(label="Member แแ แบแ Password", placeholder="แฅแแแฌ - mgmg123") | |
| add_member_btn = gr.Button("โ Paid Member แกแแ แบ แแฑแฌแแบแแแบ (แ แ แแแบแแแบแธ)", variant="secondary") | |
| gr.Markdown("---") | |
| gr.Markdown("### ๐๏ธ Member แกแฌแธ แแผแแบแแปแแบแแแบ") | |
| delete_user_in = gr.Textbox(label="แแปแแบแแญแฏแแฑแฌ Username แแญแฏ แแญแฏแแบแแแทแบแแซ", placeholder="แฅแแแฌ - member_mgmg") | |
| delete_member_btn = gr.Button("๐๏ธ Member แกแฌแธ แ แแ แบแแฒแแพ แแปแแบแแแบ", variant="stop") | |
| admin_action_status = gr.Textbox(label="๐ แแฏแแบแแฑแฌแแบแแพแฏ แกแแผแฑแกแแฑแแผแแปแแบ", interactive=False) | |
| with gr.Column(): | |
| gr.Markdown("### ๐ฅ แแแบแแพแญ Paid Members แแปแฌแธแ แฌแแแบแธ") | |
| members_table = gr.Dataframe( | |
| headers=["Username", "Password", "Expiry Date", "Last Used Date", "Today Limit"], | |
| datatype=["str", "str", "str", "str", "str"], | |
| value=get_members_table() | |
| ) | |
| # 3. ๐ฌ MAIN RECAP STUDIO BOX | |
| with gr.Group(visible=False) as main_studio_box: | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("### โ๏ธ Recap Configurations") | |
| api_key_input = gr.Textbox(label="๐ แแแบแ Gemini API Key", placeholder="AI Studio Key แแแทแบแแแบ", type="password") | |
| movie_name_input = gr.Textbox(label="๐ฟ แแฏแแบแแพแแบ แแญแฏแทแแแฏแแบ แ แฎแธแแฎแธแแฌแแแบ", placeholder="แฅแแแฌ- True Education (Korean Series)") | |
| episode_input = gr.Textbox(label="๐ฌ แกแแญแฏแแบแธ (Episode / Part / Season) (Optional)", placeholder="แฅแแแฌ- Episode 1") | |
| movie_context_input = gr.Textbox( | |
| label="๐ แแฌแแบแแแบแธแกแแปแแบแธ แแญแฏแทแแแฏแแบ แกแแปแแบแกแแแบ (Optional)", | |
| placeholder="แแญแฏแแญแฏแแญแแปแ แฑแแแบ แแฌแแบแแแบแธแกแแปแแบแธแแญแฏ แแแทแบแแฑแธแแญแฏแแบแแซแแแบแ", | |
| lines=4 | |
| ) | |
| duration_dropdown = gr.Dropdown( | |
| choices=["Short (TikTok/Reels - 1 Min)", "Medium (YouTube - 3 to 5 Mins)", "Long (YouTube - 10 to 15 Mins)"], | |
| value="Medium (YouTube - 3 to 5 Mins)", | |
| label="โฑ๏ธ แแฎแแฎแแญแฏ แกแแปแญแแบแกแแพแแบ" | |
| ) | |
| submit_btn = gr.Button("๐ Auto Process แ แแแบแแแบ", variant="primary") | |
| with gr.Column(): | |
| gr.Markdown("### ๐ แแฝแแบแแฑแซแบแแฌแแฑแฌ แแแแบ") | |
| output_script = gr.Textbox(label="๐ แแฝแแบแแฌแแแทแบ แแผแแบแแฌแแญแฏ Script", interactive=False, lines=18) | |
| # ๐ Login แแฏแแบแแฑแฌแแบแแปแแบ แแปแญแแบแแแบแแผแแบแธ | |
| def login_pipeline(u, p): | |
| box_vis, studio_vis, admin_vis, msg = check_login(u, p) | |
| logged_user = u.strip() if "โ" not in msg and "๐ซ" not in msg else "" | |
| return box_vis, studio_vis, admin_vis, msg, logged_user | |
| login_btn.click( | |
| fn=login_pipeline, | |
| inputs=[username_input, password_input], | |
| outputs=[login_box, main_studio_box, admin_panel, status_output, current_logged_user] | |
| ) | |
| # ๐ Script แแฏแแบแแฏแแบแแผแแบแธ แแแฏแแบแแปแญแแบแแแบแแผแแบแธ | |
| submit_btn.click( | |
| fn=process_movie_recap, | |
| inputs=[current_logged_user, movie_name_input, episode_input, movie_context_input, api_key_input, duration_dropdown], | |
| outputs=[output_script] | |
| ) | |
| # ๐ Admin Add Member | |
| add_member_btn.click( | |
| fn=admin_add_member, | |
| inputs=[new_user_in, new_pass_in], | |
| outputs=[admin_action_status, members_table] | |
| ) | |
| # ๐ Admin Delete Member | |
| delete_member_btn.click( | |
| fn=admin_delete_member, | |
| inputs=[delete_user_in], | |
| outputs=[admin_action_status, members_table] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |