vidpro2ta / app.py
Ezmary's picture
Create app.py
f6a570d verified
Raw
History Blame
6.95 kB
# app.py
import os
import json
import time
from flask import Flask, request, jsonify, render_template
from flask_cors import CORS
import logging
import threading
from huggingface_hub import HfApi, hf_hub_download
from huggingface_hub.utils import RepositoryNotFoundError, EntryNotFoundError
# --- تنظیمات اصلی ---
# !مهم: نام دیتاست خصوصی که ساختید را اینجا وارد کنید
DATASET_REPO = "Ezmary/Karbaran-rayegan-tedad" # مثال: "YourUsername/VideoUsageData"
DATASET_FILENAME = "video_usage_data.json"
USAGE_LIMIT = 5 # هر کاربر رایگان می‌تواند ۵ ویدیو در هفته بسازد
HF_TOKEN = os.environ.get("HF_TOKEN")
# --- راه‌اندازی Flask و لاگ‌ها ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
app = Flask(__name__)
CORS(app)
# --- مدیریت داده‌های کاربران ---
usage_data_cache = []
cache_lock = threading.Lock()
data_changed = threading.Event()
api = None
if not HF_TOKEN:
logging.error("CRITICAL: Secret 'HF_TOKEN' not found. Cannot access the private dataset.")
else:
api = HfApi(token=HF_TOKEN)
logging.info("HfApi initialized successfully.")
def load_initial_data():
global usage_data_cache
with cache_lock:
if not api: return
try:
logging.info(f"Attempting to load data from '{DATASET_REPO}'...")
local_path = hf_hub_download(
repo_id=DATASET_REPO,
filename=DATASET_FILENAME,
repo_type="dataset",
token=HF_TOKEN,
force_download=True
)
with open(local_path, 'r', encoding='utf-8') as f:
content = f.read()
usage_data_cache = json.loads(content) if content else []
logging.info(f"Loaded {len(usage_data_cache)} records.")
except (RepositoryNotFoundError, EntryNotFoundError):
logging.warning("Dataset file not found. A new one will be created.")
usage_data_cache = []
except Exception as e:
logging.error(f"Failed to load initial data: {e}")
def persist_data_to_hub():
with cache_lock:
if not data_changed.is_set() or not api:
return
logging.info("Change detected, preparing to write to Hub...")
try:
# ایجاد یک کپی برای جلوگیری از مشکلات thread-safety
data_to_write = list(usage_data_cache)
temp_filepath = "temp_usage_data.json"
with open(temp_filepath, 'w', encoding='utf-8') as f:
json.dump(data_to_write, f, ensure_ascii=False, indent=2)
api.upload_file(
path_or_fileobj=temp_filepath,
path_in_repo=DATASET_FILENAME,
repo_id=DATASET_REPO,
repo_type="dataset",
commit_message="Update video usage data"
)
os.remove(temp_filepath)
data_changed.clear()
logging.info(f"Successfully persisted {len(data_to_write)} records to Hub.")
except Exception as e:
logging.error(f"CRITICAL: Failed to persist data to Hub: {e}")
def background_persister():
while True:
time.sleep(30) # هر ۳۰ ثانیه یکبار چک می‌کند
persist_data_to_hub()
# --- روت‌های API ---
@app.route('/')
def index():
return render_template('index.html')
def get_user_identifier(data):
# اولویت با اثرانگشت است، اگر نبود از IP استفاده می‌شود
fingerprint = data.get('fingerprint')
if fingerprint:
return str(fingerprint)
if request.headers.getlist("X-Forwarded-For"):
return request.headers.getlist("X-Forwarded-For")[0].split(',')[0].strip()
return request.remote_addr
@app.route('/api/check-credit', methods=['POST'])
def check_credit():
data = request.get_json()
if not data: return jsonify({"error": "Invalid request"}), 400
user_id = get_user_identifier(data)
if not user_id: return jsonify({"error": "User identifier is required."}), 400
with cache_lock:
now = time.time()
one_week_seconds = 7 * 24 * 60 * 60
user_record = next((user for user in usage_data_cache if user.get('id') == user_id), None)
credits_remaining = USAGE_LIMIT
limit_reached = False
reset_timestamp = 0
if user_record:
if user_record.get('week_start', 0) < (now - one_week_seconds):
user_record['count'] = 0
user_record['week_start'] = now
data_changed.set()
credits_remaining = max(0, USAGE_LIMIT - user_record.get('count', 0))
if credits_remaining == 0:
limit_reached = True
reset_timestamp = user_record.get('week_start', now) + one_week_seconds
return jsonify({
"credits_remaining": credits_remaining,
"limit_reached": limit_reached,
"reset_timestamp": reset_timestamp
})
@app.route('/api/use-credit', methods=['POST'])
def use_credit():
data = request.get_json()
if not data: return jsonify({"error": "Invalid request"}), 400
user_id = get_user_identifier(data)
if not user_id: return jsonify({"error": "User identifier is required."}), 400
with cache_lock:
now = time.time()
one_week_seconds = 7 * 24 * 60 * 60
user_record = next((user for user in usage_data_cache if user.get('id') == user_id), None)
if user_record:
if user_record.get('week_start', 0) < (now - one_week_seconds):
user_record['count'] = 0
user_record['week_start'] = now
if user_record.get('count', 0) >= USAGE_LIMIT:
reset_timestamp = user_record.get('week_start', now) + one_week_seconds
return jsonify({
"status": "limit_reached",
"credits_remaining": 0,
"reset_timestamp": reset_timestamp
}), 429 # Too Many Requests
user_record['count'] += 1
else:
user_record = {"id": user_id, "count": 1, "week_start": now}
usage_data_cache.append(user_record)
credits_remaining = USAGE_LIMIT - user_record['count']
data_changed.set()
return jsonify({"status": "success", "credits_remaining": credits_remaining})
# --- اجرای برنامه ---
if __name__ != '__main__':
load_initial_data()
persister_thread = threading.Thread(target=background_persister, daemon=True)
persister_thread.start()
if __name__ == '__main__':
port = int(os.environ.get('PORT', 7860))
app.run(host='0.0.0.0', port=port)