Spaces:
Running
Running
from flask import Flask, render_template, request, redirect, url_for, jsonify, session | |
import requests | |
import os | |
import json | |
from datetime import timedelta | |
import logging | |
# ๋ก๊น ์ค์ | |
logging.basicConfig(level=logging.DEBUG, | |
format='%(asctime)s - %(levelname)s - %(message)s') | |
logger = logging.getLogger(__name__) | |
app = Flask(__name__) | |
app.secret_key = os.urandom(24) # ์ธ์ ์ํธํ๋ฅผ ์ํ ๋น๋ฐ ํค | |
app.permanent_session_lifetime = timedelta(days=7) # ์ธ์ ์ ์ง ๊ธฐ๊ฐ ์ค์ | |
# ์ข์์ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ ํจ์ - ๋๋ฒ๊น ๊ฐ์ | |
def get_liked_repos(token): | |
headers = {"Authorization": f"Bearer {token}"} | |
liked_models = {} | |
# 1. API์ ์ง์ ์ง์ | |
endpoints = [ | |
"/api/me/likes", | |
"/api/me/liked-repos", | |
"/api/me/favorites" | |
] | |
logger.debug(f"ํ ํฐ์ผ๋ก ์ข์์ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ ์๋ (ํ ํฐ ์ผ๋ถ: {token[:4]}...)") | |
for endpoint in endpoints: | |
logger.debug(f"์๋ํฌ์ธํธ ์๋: {endpoint}") | |
try: | |
full_url = f"https://huggingface.co{endpoint}" | |
logger.debug(f"API ํธ์ถ: {full_url}") | |
response = requests.get(full_url, headers=headers) | |
logger.debug(f"์๋ต ์ํ: {response.status_code}") | |
if response.ok: | |
data = response.json() | |
logger.debug(f"์๋ต ๋ฐ์ดํฐ ํ์ : {type(data)}") | |
logger.debug(f"๋ฐ์ดํฐ ์ํ: {str(data)[:200]}") | |
if isinstance(data, list): | |
logger.debug(f"๋ชฉ๋ก ๊ธธ์ด: {len(data)}") | |
for i, model in enumerate(data[:5]): # ์ฒ์ 5๊ฐ๋ง ๋ก๊น | |
logger.debug(f"๋ชจ๋ธ {i}: {model}") | |
if isinstance(model, dict): | |
# ๋ค์ํ API ์๋ต ๊ตฌ์กฐ ์ฒ๋ฆฌ | |
if 'owner' in model and 'name' in model: | |
model_id = f"{model['owner']}/{model['name']}" | |
liked_models[model_id] = True | |
logger.debug(f"์ถ๊ฐ๋ ๋ชจ๋ธ ID: {model_id}") | |
elif 'id' in model: | |
liked_models[model['id']] = True | |
logger.debug(f"์ถ๊ฐ๋ ๋ชจ๋ธ ID: {model['id']}") | |
elif 'modelId' in model: | |
liked_models[model['modelId']] = True | |
logger.debug(f"์ถ๊ฐ๋ ๋ชจ๋ธ ID: {model['modelId']}") | |
else: | |
# ๋ค๋ฅธ ํ๋ ํ์ธ | |
logger.debug(f"๋ชจ๋ธ ํค: {list(model.keys())}") | |
# ์ง์ owner/repo ํ์ ์ถ์ถ ์๋ | |
if 'repo' in model and 'rowner' in model: | |
model_id = f"{model['rowner']}/{model['repo']}" | |
liked_models[model_id] = True | |
logger.debug(f"์ถ๊ฐ๋ ๋ชจ๋ธ ID: {model_id}") | |
elif isinstance(data, dict): | |
logger.debug(f"๊ฐ์ฒด ํค: {list(data.keys())}") | |
# ๊ฐ์ฒด ๊ตฌ์กฐ์ ๋ฐ๋ผ ์ฒ๋ฆฌ | |
if 'models' in data and isinstance(data['models'], list): | |
for model in data['models']: | |
if isinstance(model, dict) and 'id' in model: | |
liked_models[model['id']] = True | |
logger.debug(f"์ถ๊ฐ๋ ๋ชจ๋ธ ID: {model['id']}") | |
else: | |
# ๋จ์ ํค-๊ฐ ๊ตฌ์กฐ๋ผ๋ฉด | |
for key in data: | |
liked_models[key] = True | |
logger.debug(f"์ถ๊ฐ๋ ํค: {key}") | |
logger.debug(f"์ด ์ข์์ ํญ๋ชฉ ์: {len(liked_models)}") | |
if len(liked_models) > 0: | |
logger.debug("์ข์์ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ ์ฑ๊ณต!") | |
return liked_models | |
else: | |
logger.debug(f"API ์ค๋ฅ: {response.text}") | |
except Exception as e: | |
logger.error(f"์๋ํฌ์ธํธ {endpoint} ์ค๋ฅ: {str(e)}") | |
# 2. ์๋ ์คํ์ด์ค/๋ชจ๋ธ ํ์ธ (API๊ฐ ์คํจํ ๊ฒฝ์ฐ) | |
logger.debug("API ์กฐํ ์คํจ, ์๋ ์คํ์ด์ค/๋ชจ๋ธ ํ์ธ ์๋") | |
try: | |
# "me" ํ์ด์ง ์ ๊ทผํด์ HTML์์ ์ข์์ ์ ๋ณด ์ฐพ๊ธฐ | |
response = requests.get("https://huggingface.co/me/likes", headers=headers) | |
if response.ok: | |
logger.debug("์ข์์ ํ์ด์ง ๊ฐ์ ธ์ค๊ธฐ ์ฑ๊ณต") | |
# ์ฌ๊ธฐ์ HTML ํ์ฑํ ์๋ ์์ง๋ง ๋ณต์กํ๋ฏ๋ก ์๋ต | |
except Exception as e: | |
logger.error(f"์๋ ํ์ธ ์ค๋ฅ: {str(e)}") | |
# 3. API ๊ฒฐ๊ณผ ํ์ธ ํ์ด์ง ์ถ๊ฐ (๋๋ฒ๊น ์ฉ) | |
def debug_likes(): | |
if 'token' not in session: | |
return jsonify({'success': False, 'message': '๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค.'}) | |
headers = {"Authorization": f"Bearer {session['token']}"} | |
results = {} | |
for endpoint in ["/api/me/likes", "/api/me/liked-repos", "/api/me/favorites"]: | |
try: | |
response = requests.get(f"https://huggingface.co{endpoint}", headers=headers) | |
results[endpoint] = { | |
'status': response.status_code, | |
'ok': response.ok, | |
'data': response.json() if response.ok else None | |
} | |
except Exception as e: | |
results[endpoint] = {'error': str(e)} | |
return jsonify(results) | |
# ์ข์์ ์ํ๊ฐ ์๋ ๊ฒฝ์ฐ ๋น ๊ฐ์ฒด ๋ฐํ | |
logger.debug("์ข์์ ๋ชฉ๋ก ์์, ๋น ๊ฐ์ฒด ๋ฐํ") | |
return liked_models | |
# ๋ฉ์ธ ์ฑ์ฉ ํ๋๊ทธ๋ฅผ ์ถ๊ฐํด ๋๋ฒ๊น ์๋ํฌ์ธํธ ์ถ๊ฐ | |
def add_debug_endpoints(app): | |
def debug_likes(): | |
if 'token' not in session: | |
return jsonify({'success': False, 'message': '๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค.'}) | |
headers = {"Authorization": f"Bearer {session['token']}"} | |
results = {} | |
for endpoint in ["/api/me/likes", "/api/me/liked-repos", "/api/me/favorites"]: | |
try: | |
response = requests.get(f"https://huggingface.co{endpoint}", headers=headers) | |
results[endpoint] = { | |
'status': response.status_code, | |
'ok': response.ok | |
} | |
# ์ฑ๊ณตํ ๊ฒฝ์ฐ์๋ง ๋ฐ์ดํฐ ์ถ๊ฐ | |
if response.ok: | |
try: | |
results[endpoint]['data'] = response.json() | |
except Exception as e: | |
results[endpoint]['parse_error'] = str(e) | |
except Exception as e: | |
results[endpoint] = {'error': str(e)} | |
# ํ์ฌ ์ธ์ ์ ์ ์ฅ๋ ์ข์์ ๋ชฉ๋ก ๋ฐํ | |
results['current_session_likes'] = { | |
'count': len(session.get('liked_models', {})), | |
'items': list(session.get('liked_models', {}).keys()) | |
} | |
return jsonify(results) | |
def debug_urls(): | |
# ๋ชจ๋ธ ์ ๋ณด ์ถ์ถ ๋๋ฒ๊น | |
from urllib.parse import urlparse | |
test_urls = [ | |
"https://huggingface.co/spaces/ginipick/Tech_Hangman_Game", | |
"https://huggingface.co/models/meta/llama-2", | |
"https://huggingface.co/meta/llama-2" | |
] | |
results = {} | |
for url in test_urls: | |
try: | |
parsed = urlparse(url) | |
path_parts = parsed.path.split('/') | |
path_parts = [p for p in path_parts if p] # ๋น ๋ฌธ์์ด ์ ๊ฑฐ | |
result = { | |
'parsed_url': { | |
'scheme': parsed.scheme, | |
'netloc': parsed.netloc, | |
'path': parsed.path, | |
'path_parts': path_parts | |
} | |
} | |
# ๊ฒฝ๋ก ํ์ฑ | |
if len(path_parts) >= 2: | |
if path_parts[0] == 'spaces' or path_parts[0] == 'models': | |
result['extract'] = { | |
'type': path_parts[0], | |
'owner': path_parts[1], | |
'repo': path_parts[2] if len(path_parts) > 2 else None, | |
'full_id': f"{path_parts[1]}/{path_parts[2]}" if len(path_parts) > 2 else f"{path_parts[1]}" | |
} | |
else: | |
result['extract'] = { | |
'type': 'models', # ๊ธฐ๋ณธ๊ฐ | |
'owner': path_parts[0], | |
'repo': path_parts[1] if len(path_parts) > 1 else None, | |
'full_id': f"{path_parts[0]}/{path_parts[1]}" if len(path_parts) > 1 else f"{path_parts[0]}" | |
} | |
results[url] = result | |
except Exception as e: | |
results[url] = {'error': str(e)} | |
return jsonify(results) | |
# ์ด ์คํฌ๋ฆฝํธ๊ฐ ์ง์ ์คํ๋๋ฉด ํ ์คํธ ์๋ฒ๋ฅผ ์์ | |
if __name__ == '__main__': | |
test_app = Flask(__name__) | |
test_app.secret_key = os.urandom(24) | |
# ์ธ์ ์ฟ ํค ์ค์ | |
test_app.config['SESSION_COOKIE_SECURE'] = False # HTTPS ์์ด๋ ์๋ | |
test_app.config['SESSION_COOKIE_HTTPONLY'] = True | |
add_debug_endpoints(test_app) | |
def home(): | |
return ''' | |
<h1>ํ๊น ํ์ด์ค ์ข์์ ๋๋ฒ๊ฑฐ</h1> | |
<p>๋ค์ ์๋ํฌ์ธํธ๋ก ์ ์ํ์ธ์:</p> | |
<ul> | |
<li><a href="/login-form">๋ก๊ทธ์ธ ํ์ด์ง</a></li> | |
<li><a href="/api/debug-likes">์ข์์ API ๋๋ฒ๊ทธ (๋ก๊ทธ์ธ ํ์)</a></li> | |
<li><a href="/api/debug-urls">URL ํ์ฑ ๋๋ฒ๊ทธ</a></li> | |
</ul> | |
''' | |
def login_form(): | |
return ''' | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>ํ ํฐ ๋ก๊ทธ์ธ</title> | |
<style> | |
body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; } | |
input { width: 100%; padding: 8px; margin: 10px 0; } | |
button { padding: 10px 15px; background: #4CAF50; color: white; border: none; cursor: pointer; } | |
.result { margin-top: 20px; padding: 10px; border: 1px solid #ddd; display: none; } | |
pre { background: #f5f5f5; padding: 10px; overflow-x: auto; } | |
</style> | |
</head> | |
<body> | |
<h1>ํ๊น ํ์ด์ค ํ ํฐ ํ ์คํธ</h1> | |
<p>ํ๊น ํ์ด์ค API ํ ํฐ์ ์ ๋ ฅํ์ธ์:</p> | |
<input type="password" id="tokenInput" placeholder="API ํ ํฐ" /> | |
<button id="loginBtn">๋ก๊ทธ์ธ</button> | |
<div id="result" class="result"> | |
<h3>๊ฒฐ๊ณผ</h3> | |
<pre id="resultContent"></pre> | |
</div> | |
<script> | |
const loginBtn = document.getElementById('loginBtn'); | |
const tokenInput = document.getElementById('tokenInput'); | |
const result = document.getElementById('result'); | |
const resultContent = document.getElementById('resultContent'); | |
loginBtn.addEventListener('click', async () => { | |
const token = tokenInput.value.trim(); | |
if (!token) { | |
alert('ํ ํฐ์ ์ ๋ ฅํ์ธ์'); | |
return; | |
} | |
try { | |
const formData = new FormData(); | |
formData.append('token', token); | |
const response = await fetch('/api/login-test', { | |
method: 'POST', | |
body: formData | |
}); | |
const data = await response.json(); | |
result.style.display = 'block'; | |
resultContent.textContent = JSON.stringify(data, null, 2); | |
if (data.success) { | |
// ์ฑ๊ณต ์ ์ข์์ ๋ชฉ๋ก ํ์ด์ง๋ก ์ด๋ | |
setTimeout(() => { | |
window.location.href = '/api/debug-likes'; | |
}, 2000); | |
} | |
} catch (error) { | |
result.style.display = 'block'; | |
resultContent.textContent = `์ค๋ฅ: ${error.message}`; | |
} | |
}); | |
</script> | |
</body> | |
</html> | |
''' | |
def login_test(): | |
token = request.form.get('token', '') | |
if not token: | |
return jsonify({'success': False, 'message': 'ํ ํฐ์ ์ ๋ ฅํด์ฃผ์ธ์.'}) | |
session['token'] = token | |
# ์ฌ์ฉ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ | |
user_info = None | |
for endpoint in ["https://huggingface.co/api/whoami-v2", "https://huggingface.co/api/whoami"]: | |
try: | |
headers = {"Authorization": f"Bearer {token}"} | |
response = requests.get(endpoint, headers=headers) | |
if response.ok: | |
user_info = response.json() | |
break | |
except Exception as e: | |
logger.error(f"์ฌ์ฉ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ ์ค๋ฅ: {str(e)}") | |
if not user_info: | |
return jsonify({'success': False, 'message': '์ ํจํ์ง ์์ ํ ํฐ์ ๋๋ค.'}) | |
# ์ฌ์ฉ์ ์ด๋ฆ ์ฐพ๊ธฐ | |
username = None | |
if 'name' in user_info: | |
username = user_info['name'] | |
elif 'user' in user_info and 'username' in user_info['user']: | |
username = user_info['user']['username'] | |
elif 'username' in user_info: | |
username = user_info['username'] | |
else: | |
username = '์ธ์ฆ๋ ์ฌ์ฉ์' | |
session['username'] = username | |
# ์ข์์ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ | |
liked_models = get_liked_repos(token) | |
session['liked_models'] = liked_models | |
return jsonify({ | |
'success': True, | |
'username': username, | |
'liked_models_count': len(liked_models), | |
'liked_models_sample': list(liked_models.keys())[:5] if liked_models else [] | |
}) | |
# ๋๋ฒ๊น ์๋ฒ ์คํ | |
logger.info("๋๋ฒ๊น ์๋ฒ ์์ (ํฌํธ 7860)") | |
test_app.run(host='0.0.0.0', port=7860, debug=True) |