fix: Add public API for Chrome extension (no login required) - New endpoints: /public/youtube/formats, /public/youtube/add - Update extension to use public API - Add contextMenus/notifications permissions
This commit is contained in:
@@ -5,13 +5,15 @@
|
|||||||
"description": "YouTube 영상을 GDM(gommi_downloader_manager)으로 전송하여 다운로드",
|
"description": "YouTube 영상을 GDM(gommi_downloader_manager)으로 전송하여 다운로드",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"activeTab",
|
"activeTab",
|
||||||
"storage"
|
"storage",
|
||||||
|
"contextMenus",
|
||||||
|
"notifications"
|
||||||
],
|
],
|
||||||
"host_permissions": [
|
"host_permissions": [
|
||||||
"https://www.youtube.com/*",
|
"https://www.youtube.com/*",
|
||||||
"https://youtu.be/*",
|
"https://youtu.be/*",
|
||||||
"http://localhost:*/*",
|
"http://*/*",
|
||||||
"http://127.0.0.1:*/*"
|
"https://*/*"
|
||||||
],
|
],
|
||||||
"action": {
|
"action": {
|
||||||
"default_popup": "popup.html",
|
"default_popup": "popup.html",
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ async function fetchVideoInfo() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${serverUrl}/gommi_downloader_manager/ajax/queue/youtube_formats?url=${encodeURIComponent(currentUrl)}`,
|
`${serverUrl}/gommi_downloader_manager/public/youtube/formats?url=${encodeURIComponent(currentUrl)}`,
|
||||||
{ method: 'GET' }
|
{ method: 'GET' }
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ async function startDownload() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${serverUrl}/gommi_downloader_manager/ajax/queue/youtube_add`,
|
`${serverUrl}/gommi_downloader_manager/public/youtube/add`,
|
||||||
{
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
title: "GDM"
|
title: "GDM"
|
||||||
package_name: gommi_downloader_manager
|
package_name: gommi_downloader_manager
|
||||||
version: '0.2.19'
|
version: '0.2.20'
|
||||||
description: FlaskFarm 범용 다운로더 큐 - YouTube, 애니24, 링크애니, Anilife 지원
|
description: FlaskFarm 범용 다운로더 큐 - YouTube, 애니24, 링크애니, Anilife 지원
|
||||||
developer: projectdx
|
developer: projectdx
|
||||||
home: https://gitea.yommi.duckdns.org/projectdx/gommi_downloader_manager
|
home: https://gitea.yommi.duckdns.org/projectdx/gommi_downloader_manager
|
||||||
|
|||||||
95
setup.py
95
setup.py
@@ -65,3 +65,98 @@ try:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
P.logger.error(f'Exception:{str(e)}')
|
P.logger.error(f'Exception:{str(e)}')
|
||||||
P.logger.error(traceback.format_exc())
|
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}')
|
||||||
|
|||||||
Reference in New Issue
Block a user