Opera8 commited on
Commit
70573b7
·
verified ·
1 Parent(s): ef7954e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -55
app.py CHANGED
@@ -3,7 +3,7 @@ import json
3
  import random
4
  import asyncio
5
  import re
6
- import fcntl # کتابخانه قفل کردن فایل برای دقت ۱۰۰ درصد
7
  import time
8
  from datetime import datetime
9
  from concurrent.futures import ThreadPoolExecutor
@@ -19,7 +19,7 @@ app = FastAPI()
19
 
20
  # --- تنظیمات محدودیت ---
21
  MAX_FREE_DAILY_REQUESTS = 5
22
- USAGE_DB_FILE = "usage_data.json" # فایل ذخیره سوابق
23
 
24
  # --- بخش بارگذاری کلیدها ---
25
  all_keys_str = os.getenv("ALL_GEMINI_API_KEYS", "")
@@ -42,6 +42,7 @@ class IdeaRequest(BaseModel):
42
  idea: str
43
  fingerprint: str
44
  is_premium: bool = False
 
45
 
46
  @app.get("/", response_class=HTMLResponse)
47
  async def read_root():
@@ -52,7 +53,7 @@ async def read_root():
52
  return "<h1>Error: index.html not found</h1>"
53
 
54
  def sync_generate_content(prompt):
55
- max_retries = 1000
56
  if not GEMINI_KEYS:
57
  return None
58
 
@@ -69,62 +70,46 @@ def sync_generate_content(prompt):
69
  return None
70
 
71
  def check_and_increment_usage(ip: str, fingerprint: str):
72
- """
73
- این تابع با استفاده از مکانیزم قفل (Lock) فایل، دسترسی همزمان را مدیریت می‌کند.
74
- این روش دقیق‌ترین راه برای اعمال محدودیت در محیط‌های چند-رشته‌ای است.
75
- """
76
  today = datetime.now().strftime("%Y-%m-%d")
77
-
78
- # تلاش برای ایجاد فایل اگر وجود ندارد (با مدیریت خطا برای جلوگیری از تداخل)
79
  if not os.path.exists(USAGE_DB_FILE):
80
  try:
81
  with open(USAGE_DB_FILE, 'w') as f:
82
  json.dump({}, f)
83
  except OSError:
84
- pass # ممکن است یک پردازش دیگر همزمان فایل را ساخته باشد
85
 
86
- # باز کردن فایل با قابلیت خواندن و نوشتن
87
  try:
88
  f = open(USAGE_DB_FILE, 'r+')
89
  except FileNotFoundError:
90
- # اگر فایل در لحظه باز کردن حذف شده باشد دوباره می‌سازیم
91
  f = open(USAGE_DB_FILE, 'w+')
92
  json.dump({}, f)
93
  f.seek(0)
94
 
95
  with f:
96
  try:
97
- # اعمال قفل انحصاری: بقیه درخواست‌ها منتظر می‌مانند تا این یکی تمام شود
98
  fcntl.flock(f, fcntl.LOCK_EX)
99
-
100
  try:
101
  content = f.read()
102
  data = json.loads(content) if content else {}
103
  except json.JSONDecodeError:
104
  data = {}
105
 
106
- # آماده‌سازی کلیدها
107
  ip_key = f"ip:{ip}"
108
  fp_key = f"fp:{fingerprint}"
109
 
110
- # --- منطق بررسی IP ---
111
  ip_record = data.get(ip_key, {"date": today, "count": 0})
112
- if ip_record["date"] != today: # اگر روز جدید است، ریست کن
113
  ip_record = {"date": today, "count": 0}
114
 
115
- # --- منطق بررسی اثر انگشت ---
116
  fp_record = data.get(fp_key, {"date": today, "count": 0})
117
- if fp_record["date"] != today: # اگر روز جدید است، ریست کن
118
  fp_record = {"date": today, "count": 0}
119
 
120
- # --- شرط مسدودسازی ---
121
- # اگر هر کدام از سقف رد شده باشند، اجازه نده
122
  if ip_record["count"] >= MAX_FREE_DAILY_REQUESTS:
123
  return False
124
  if fingerprint and fp_record["count"] >= MAX_FREE_DAILY_REQUESTS:
125
  return False
126
 
127
- # --- ثبت استفاده ---
128
  ip_record["count"] += 1
129
  data[ip_key] = ip_record
130
 
@@ -132,16 +117,13 @@ def check_and_increment_usage(ip: str, fingerprint: str):
132
  fp_record["count"] += 1
133
  data[fp_key] = fp_record
134
 
135
- # بازنویسی فایل با داده‌های جدید
136
  f.seek(0)
137
  f.truncate()
138
  json.dump(data, f)
139
- f.flush() # اطمینان از نوشته شدن روی دیسک
140
-
141
  return True
142
 
143
  finally:
144
- # آزاد کردن قفل
145
  fcntl.flock(f, fcntl.LOCK_UN)
146
 
147
  @app.post("/api/refine")
@@ -149,54 +131,47 @@ async def refine_text(request: IdeaRequest, req: Request):
149
  if not GEMINI_KEYS:
150
  raise HTTPException(status_code=500, detail="کلید API تنظیم نشده است.")
151
 
152
- # --- بررسی دقیق محدودیت روزانه ---
153
  if not request.is_premium:
154
  client_ip = req.client.host
155
  client_fp = request.fingerprint
156
-
157
- # فراخوانی تابع با قفل فایل
158
  try:
159
  allowed = check_and_increment_usage(client_ip, client_fp)
160
- except Exception as e:
161
- print(f"Error checking limit: {e}")
162
- # در صورت بروز خطای سیستمی، برای اطمینان کاربر را بلاک می‌کنیم یا باز می‌گذاریم؟
163
- # اینجا برای امنیت بیشتر، اجازه نمی‌دهیم.
164
  return JSONResponse(content={"error": "System Error checking limits"}, status_code=500)
165
 
166
  if not allowed:
167
- # کد 429 به معنی Too Many Requests
168
  return JSONResponse(content={"error": "LIMIT_REACHED"}, status_code=429)
169
- # ---------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
  prompt = f"""
172
  You are a professional songwriter and music producer.
173
  Task: Convert the user's input into a COMPLETE song structure and a music generation prompt.
 
 
174
 
175
  1. **Music Prompt (English):** Describe the mood, instruments, BPM, and style suitable for an AI music generator.
176
 
177
- 2. **Lyrics (Match User's Language):**
178
- - **Language Detection:** Detect the language of the "User Input".
179
- - **Write the lyrics entirely in that detected language.**
180
- - The song MUST be long enough for **3 to 5 minutes**.
181
- - You MUST use the following structure tags exactly:
182
- [Verse 1]
183
- [Pre-Chorus]
184
- [Chorus]
185
- [Verse 2]
186
- [Chorus]
187
- [Bridge]
188
- [Chorus]
189
- [Outro]
190
-
191
- **CRITICAL RULES FOR LYRICS content:**
192
- - The "lyrics" field must contain **ONLY the words to be sung**.
193
- - **ABSOLUTELY NO** descriptive text inside the lyrics.
194
- - For instrumental sections, leave the content empty.
195
-
196
  Output strictly in JSON format:
197
  {{
198
  "music_prompt": "YOUR ENGLISH PROMPT HERE",
199
- "lyrics": "YOUR FULL LYRICS HERE"
200
  }}
201
 
202
  User Input: {request.idea}
 
3
  import random
4
  import asyncio
5
  import re
6
+ import fcntl
7
  import time
8
  from datetime import datetime
9
  from concurrent.futures import ThreadPoolExecutor
 
19
 
20
  # --- تنظیمات محدودیت ---
21
  MAX_FREE_DAILY_REQUESTS = 5
22
+ USAGE_DB_FILE = "usage_data.json"
23
 
24
  # --- بخش بارگذاری کلیدها ---
25
  all_keys_str = os.getenv("ALL_GEMINI_API_KEYS", "")
 
42
  idea: str
43
  fingerprint: str
44
  is_premium: bool = False
45
+ is_instrumental: bool = False # فیلد جدید برای حالت بی‌کلام
46
 
47
  @app.get("/", response_class=HTMLResponse)
48
  async def read_root():
 
53
  return "<h1>Error: index.html not found</h1>"
54
 
55
  def sync_generate_content(prompt):
56
+ max_retries = 3
57
  if not GEMINI_KEYS:
58
  return None
59
 
 
70
  return None
71
 
72
  def check_and_increment_usage(ip: str, fingerprint: str):
 
 
 
 
73
  today = datetime.now().strftime("%Y-%m-%d")
 
 
74
  if not os.path.exists(USAGE_DB_FILE):
75
  try:
76
  with open(USAGE_DB_FILE, 'w') as f:
77
  json.dump({}, f)
78
  except OSError:
79
+ pass
80
 
 
81
  try:
82
  f = open(USAGE_DB_FILE, 'r+')
83
  except FileNotFoundError:
 
84
  f = open(USAGE_DB_FILE, 'w+')
85
  json.dump({}, f)
86
  f.seek(0)
87
 
88
  with f:
89
  try:
 
90
  fcntl.flock(f, fcntl.LOCK_EX)
 
91
  try:
92
  content = f.read()
93
  data = json.loads(content) if content else {}
94
  except json.JSONDecodeError:
95
  data = {}
96
 
 
97
  ip_key = f"ip:{ip}"
98
  fp_key = f"fp:{fingerprint}"
99
 
 
100
  ip_record = data.get(ip_key, {"date": today, "count": 0})
101
+ if ip_record["date"] != today:
102
  ip_record = {"date": today, "count": 0}
103
 
 
104
  fp_record = data.get(fp_key, {"date": today, "count": 0})
105
+ if fp_record["date"] != today:
106
  fp_record = {"date": today, "count": 0}
107
 
 
 
108
  if ip_record["count"] >= MAX_FREE_DAILY_REQUESTS:
109
  return False
110
  if fingerprint and fp_record["count"] >= MAX_FREE_DAILY_REQUESTS:
111
  return False
112
 
 
113
  ip_record["count"] += 1
114
  data[ip_key] = ip_record
115
 
 
117
  fp_record["count"] += 1
118
  data[fp_key] = fp_record
119
 
 
120
  f.seek(0)
121
  f.truncate()
122
  json.dump(data, f)
123
+ f.flush()
 
124
  return True
125
 
126
  finally:
 
127
  fcntl.flock(f, fcntl.LOCK_UN)
128
 
129
  @app.post("/api/refine")
 
131
  if not GEMINI_KEYS:
132
  raise HTTPException(status_code=500, detail="کلید API تنظیم نشده است.")
133
 
 
134
  if not request.is_premium:
135
  client_ip = req.client.host
136
  client_fp = request.fingerprint
 
 
137
  try:
138
  allowed = check_and_increment_usage(client_ip, client_fp)
139
+ except Exception:
 
 
 
140
  return JSONResponse(content={"error": "System Error checking limits"}, status_code=500)
141
 
142
  if not allowed:
 
143
  return JSONResponse(content={"error": "LIMIT_REACHED"}, status_code=429)
144
+
145
+ # لاجیک جدید برای حالت بی‌کلام
146
+ instruction = ""
147
+ if request.is_instrumental:
148
+ instruction = """
149
+ **INSTRUMENTAL MODE ACTIVE:**
150
+ - The user wants an instrumental song (NO LYRICS).
151
+ - **lyrics field MUST be an empty string ""**.
152
+ - Focus entirely on the `music_prompt` to describe the instruments and mood vividly.
153
+ """
154
+ else:
155
+ instruction = """
156
+ - **Lyrics (Match User's Language):**
157
+ - Detect the language of the "User Input".
158
+ - Write the lyrics entirely in that detected language.
159
+ - Structure tags: [Verse 1], [Chorus], etc.
160
+ - "lyrics" field must contain ONLY words to be sung.
161
+ """
162
 
163
  prompt = f"""
164
  You are a professional songwriter and music producer.
165
  Task: Convert the user's input into a COMPLETE song structure and a music generation prompt.
166
+
167
+ {instruction}
168
 
169
  1. **Music Prompt (English):** Describe the mood, instruments, BPM, and style suitable for an AI music generator.
170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  Output strictly in JSON format:
172
  {{
173
  "music_prompt": "YOUR ENGLISH PROMPT HERE",
174
+ "lyrics": "YOUR FULL LYRICS HERE (OR EMPTY STRING IF INSTRUMENTAL)"
175
  }}
176
 
177
  User Input: {request.idea}