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