Update app.py
Browse files
app.py
CHANGED
|
@@ -3,7 +3,8 @@ import json
|
|
| 3 |
import random
|
| 4 |
import asyncio
|
| 5 |
import re
|
| 6 |
-
import fcntl # ب
|
|
|
|
| 7 |
from datetime import datetime
|
| 8 |
from concurrent.futures import ThreadPoolExecutor
|
| 9 |
from fastapi import FastAPI, HTTPException, Request
|
|
@@ -69,24 +70,36 @@ def sync_generate_content(prompt):
|
|
| 69 |
|
| 70 |
def check_and_increment_usage(ip: str, fingerprint: str):
|
| 71 |
"""
|
| 72 |
-
این تابع با استفاده از قفل فایل، دسترسی همزمان
|
| 73 |
-
|
| 74 |
"""
|
| 75 |
today = datetime.now().strftime("%Y-%m-%d")
|
| 76 |
|
| 77 |
-
# ا
|
| 78 |
if not os.path.exists(USAGE_DB_FILE):
|
| 79 |
-
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
# باز کردن فایل با قابلیت خواندن و نوشتن
|
| 83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
try:
|
| 85 |
-
# اعمال قفل انحصاری
|
| 86 |
fcntl.flock(f, fcntl.LOCK_EX)
|
| 87 |
|
| 88 |
try:
|
| 89 |
-
|
|
|
|
| 90 |
except json.JSONDecodeError:
|
| 91 |
data = {}
|
| 92 |
|
|
@@ -94,23 +107,24 @@ def check_and_increment_usage(ip: str, fingerprint: str):
|
|
| 94 |
ip_key = f"ip:{ip}"
|
| 95 |
fp_key = f"fp:{fingerprint}"
|
| 96 |
|
| 97 |
-
#
|
| 98 |
ip_record = data.get(ip_key, {"date": today, "count": 0})
|
| 99 |
-
if ip_record["date"] != today: # ر
|
| 100 |
ip_record = {"date": today, "count": 0}
|
| 101 |
|
| 102 |
-
#
|
| 103 |
fp_record = data.get(fp_key, {"date": today, "count": 0})
|
| 104 |
-
if fp_record["date"] != today: # ر
|
| 105 |
fp_record = {"date": today, "count": 0}
|
| 106 |
|
| 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 |
-
#
|
| 114 |
ip_record["count"] += 1
|
| 115 |
data[ip_key] = ip_record
|
| 116 |
|
|
@@ -118,10 +132,11 @@ def check_and_increment_usage(ip: str, fingerprint: str):
|
|
| 118 |
fp_record["count"] += 1
|
| 119 |
data[fp_key] = fp_record
|
| 120 |
|
| 121 |
-
# بازنویسی فایل
|
| 122 |
f.seek(0)
|
| 123 |
f.truncate()
|
| 124 |
json.dump(data, f)
|
|
|
|
| 125 |
|
| 126 |
return True
|
| 127 |
|
|
@@ -139,8 +154,14 @@ async def refine_text(request: IdeaRequest, req: Request):
|
|
| 139 |
client_ip = req.client.host
|
| 140 |
client_fp = request.fingerprint
|
| 141 |
|
| 142 |
-
# فراخوانی تابع ا
|
| 143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
|
| 145 |
if not allowed:
|
| 146 |
# کد 429 به معنی Too Many Requests
|
|
|
|
| 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
|
| 10 |
from fastapi import FastAPI, HTTPException, Request
|
|
|
|
| 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 |
|
|
|
|
| 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 |
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 |
|
|
|
|
| 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
|