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 결과 확인 페이지 추가 (디버깅용) @app.route('/api/debug-likes', methods=['GET']) 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): @app.route('/api/debug-likes', methods=['GET']) 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) @app.route('/api/debug-urls', methods=['GET']) 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) @test_app.route('/') def home(): return '''

허깅페이스 좋아요 디버거

다음 엔드포인트로 접속하세요:

''' @test_app.route('/login-form') def login_form(): return ''' 토큰 로그인

허깅페이스 토큰 테스트

허깅페이스 API 토큰을 입력하세요:

결과


            
''' @test_app.route('/api/login-test', methods=['POST']) 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)