Files
gommi_downloader_manager/setup.py

163 lines
5.6 KiB
Python

"""
gommi_download_manager - FlaskFarm 범용 다운로더 큐 플러그인
지원 소스:
- YouTube (yt-dlp + aria2c)
- 애니24/링크애니 (ffmpeg HLS)
- Anilife (Camoufox + ffmpeg)
- 기타 HTTP 직접 다운로드
성능 최적화:
- aria2c 멀티커넥션 (16개 동시 연결)
- 직접 import 방식 (API 오버헤드 제거)
- asyncio 큐 처리
"""
import traceback
import os
package_name = os.path.basename(os.path.dirname(os.path.abspath(__file__)))
setting = {
'filepath': __file__,
'use_db': True,
'use_default_setting': True,
'home_module': 'queue',
'package_name': package_name,
'menu': {
'uri': package_name,
'name': 'GDM',
'list': [
{
'uri': 'queue',
'name': '다운로드 큐',
'list': [
{'uri': 'setting', 'name': '설정'},
{'uri': 'list', 'name': '다운로드 목록'},
]
},
{
'uri': 'manual',
'name': '매뉴얼',
'list': [
{'uri': 'README.md', 'name': 'README'},
]
},
{'uri': 'log', 'name': '로그'},
]
},
'default_route': 'normal',
}
from plugin import *
P = create_plugin_instance(setting)
try:
import flask
from flask import Blueprint
from .model import ModelSetting, ModelDownloadItem
except ImportError:
pass
try:
from .mod_queue import ModuleQueue
P.set_module_list([ModuleQueue])
except Exception as e:
P.logger.error(f'Exception:{str(e)}')
P.logger.error(traceback.format_exc())
# ===== Public API for Chrome Extension (No Login Required) =====
try:
from flask import Blueprint, request, jsonify
public_api = Blueprint(f'{package_name}_public_api', package_name, url_prefix=f'/{package_name}/public')
@public_api.route('/youtube/formats', methods=['GET', 'POST'])
def youtube_formats():
"""YouTube 품질 목록 조회 (인증 불필요)"""
url = request.args.get('url') or request.form.get('url', '')
if not url:
return jsonify({'ret': 'error', 'msg': 'URL이 필요합니다.'})
try:
import yt_dlp
ydl_opts = {'quiet': True, 'no_warnings': True}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=False)
formats = [{'id': 'bestvideo+bestaudio/best', 'label': '최고 품질', 'note': ''}]
heights = set()
for f in info.get('formats', []):
h = f.get('height')
if h and f.get('vcodec') != 'none':
heights.add(h)
for h in sorted(heights, reverse=True):
if h >= 2160: formats.append({'id': 'bestvideo[height<=2160]+bestaudio/best', 'label': '4K', 'note': ''})
elif h >= 1080: formats.append({'id': 'bestvideo[height<=1080]+bestaudio/best', 'label': '1080p', 'note': '권장'})
elif h >= 720: formats.append({'id': 'bestvideo[height<=720]+bestaudio/best', 'label': '720p', 'note': ''})
formats.append({'id': 'bestaudio/best', 'label': '오디오만', 'note': ''})
# 중복 제거
seen, unique = set(), []
for f in formats:
if f['id'] not in seen:
seen.add(f['id'])
unique.append(f)
return jsonify({
'ret': 'success',
'title': info.get('title', ''),
'thumbnail': info.get('thumbnail', ''),
'duration': info.get('duration', 0),
'formats': unique
})
except Exception as e:
return jsonify({'ret': 'error', 'msg': str(e)})
@public_api.route('/youtube/add', methods=['POST'])
def youtube_add():
"""YouTube 다운로드 추가 (인증 불필요)"""
try:
if request.is_json:
data = request.get_json()
else:
data = request.form.to_dict()
url = data.get('url', '')
if not url or ('youtube.com' not in url and 'youtu.be' not in url):
return jsonify({'ret': 'error', 'msg': '유효한 YouTube URL이 필요합니다.'})
format_id = data.get('format', 'bestvideo+bestaudio/best')
from framework import F
from tool import ToolUtil
save_path = ToolUtil.make_path(P.ModelSetting.get('save_path'))
item = ModuleQueue.add_download(
url=url,
save_path=save_path,
source_type='youtube',
caller_plugin='chrome_extension',
format=format_id
)
if item:
return jsonify({'ret': 'success', 'id': item.id, 'msg': '다운로드가 추가되었습니다.'})
else:
return jsonify({'ret': 'error', 'msg': '다운로드 추가 실패'})
except Exception as e:
P.logger.error(f'Public API youtube_add error: {e}')
return jsonify({'ret': 'error', 'msg': str(e)})
# Blueprint 등록
from framework import F
F.app.register_blueprint(public_api)
P.logger.info(f'Public API registered: /{package_name}/public/')
except Exception as e:
P.logger.warning(f'Public API registration failed: {e}')