Update repository URL to Gitea and sync structural changes
This commit is contained in:
@@ -1,7 +0,0 @@
|
|||||||
from .plugin import Plugin
|
|
||||||
|
|
||||||
blueprint = Plugin.blueprint
|
|
||||||
menu = Plugin.menu
|
|
||||||
plugin_load = Plugin.logic.plugin_load
|
|
||||||
plugin_unload = Plugin.logic.plugin_unload
|
|
||||||
plugin_info = Plugin.plugin_info
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "4.0.1",
|
|
||||||
"name": "youtube-dl",
|
|
||||||
"category_name": "vod",
|
|
||||||
"developer": "joyfuI",
|
|
||||||
"description": "유튜브, 네이버TV 등 동영상 사이트에서 동영상 다운로드",
|
|
||||||
"home": "https://github.com/joyfuI/youtube-dl",
|
|
||||||
"more": ""
|
|
||||||
}
|
|
||||||
7
info.yaml
Normal file
7
info.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
title: "유튜브 다운로더"
|
||||||
|
version: "0.1.0"
|
||||||
|
package_name: "youtube-dl"
|
||||||
|
developer: "flaskfarm"
|
||||||
|
description: "유튜브 다운로드"
|
||||||
|
home: "https://gitea.yommi.duckdns.org/ff_plugins/youtube-dl"
|
||||||
|
more: "https://gitea.yommi.duckdns.org/ff_plugins/youtube-dl/raw/branch/main/README.md"
|
||||||
10
main.py
10
main.py
@@ -8,15 +8,11 @@ from datetime import datetime
|
|||||||
|
|
||||||
from flask import render_template, jsonify
|
from flask import render_template, jsonify
|
||||||
|
|
||||||
from framework import db, path_app_root, path_data, socketio
|
|
||||||
from framework.common.plugin import LogicModuleBase, default_route_socketio
|
|
||||||
|
|
||||||
from .plugin import Plugin
|
|
||||||
from .my_youtube_dl import MyYoutubeDL, Status
|
from .my_youtube_dl import MyYoutubeDL, Status
|
||||||
|
|
||||||
logger = Plugin.logger
|
logger = P.logger
|
||||||
package_name = Plugin.package_name
|
package_name = P.package_name
|
||||||
ModelSetting = Plugin.ModelSetting
|
ModelSetting = P.ModelSetting
|
||||||
|
|
||||||
|
|
||||||
class LogicMain(LogicModuleBase):
|
class LogicMain(LogicModuleBase):
|
||||||
|
|||||||
118
mod_basic.py
Normal file
118
mod_basic.py
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2023/02/25 7:29 PM
|
||||||
|
# @Author : yommi
|
||||||
|
# @Site :
|
||||||
|
# @File : mod_basic
|
||||||
|
# @Software: PyCharm
|
||||||
|
# @Path : youtube-dl/mod_basic.py
|
||||||
|
from support import SupportYaml
|
||||||
|
from tool import ToolUtil
|
||||||
|
|
||||||
|
from .setup import *
|
||||||
|
|
||||||
|
# from .main import LogicMain
|
||||||
|
from .my_youtube_dl import MyYoutubeDL, Status
|
||||||
|
import platform
|
||||||
|
import os
|
||||||
|
from .model import ModelYoutubeDlItem
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleBasic(PluginModuleBase):
|
||||||
|
def __init__(self, P):
|
||||||
|
super(ModuleBasic, self).__init__(
|
||||||
|
P, name="basic", first_menu="setting", scheduler_desc="유튜브 다운로더"
|
||||||
|
)
|
||||||
|
self.db_default = {
|
||||||
|
"db_version": "2",
|
||||||
|
"youtube_dl_package": "1",
|
||||||
|
"ffmpeg_path": ""
|
||||||
|
if platform.system() != "Windows"
|
||||||
|
else os.path.join("PATH_APP_ROOT", "bin", "Windows", "ffmpeg.exe"),
|
||||||
|
"temp_path": os.path.join("{PATH_DATA}", "download_tmp"),
|
||||||
|
"save_path": os.path.join("{PATH_DATA}", "download"),
|
||||||
|
"default_filename": "",
|
||||||
|
"proxy": "",
|
||||||
|
}
|
||||||
|
self.web_list_model = ModelYoutubeDlItem
|
||||||
|
|
||||||
|
def process_menu(self, sub, req):
|
||||||
|
logger.debug(f"sub: {sub}")
|
||||||
|
arg = P.ModelSetting.to_dict()
|
||||||
|
logger.debug(f"arg:: {arg}")
|
||||||
|
if sub == "setting":
|
||||||
|
arg["is_include"] = F.scheduler.is_include(self.get_scheduler_name())
|
||||||
|
arg["is_running"] = F.scheduler.is_running(self.get_scheduler_name())
|
||||||
|
|
||||||
|
elif sub == "download":
|
||||||
|
default_filename = P.ModelSetting.get("default_filename")
|
||||||
|
arg["filename"] = (
|
||||||
|
default_filename
|
||||||
|
if default_filename
|
||||||
|
else ModuleBasic.get_default_filename()
|
||||||
|
)
|
||||||
|
arg["preset_list"] = ModuleBasic.get_preset_list()
|
||||||
|
arg["postprocessor_list"] = ModuleBasic.get_postprocessor_list()
|
||||||
|
|
||||||
|
return render_template(f"{P.package_name}_{self.name}_{sub}.html", arg=arg)
|
||||||
|
|
||||||
|
def process_command(self, command, arg1, arg2, arg3, req):
|
||||||
|
ret = {"ret": "success"}
|
||||||
|
return jsonify(ret)
|
||||||
|
|
||||||
|
# def plugin_load(self):
|
||||||
|
# if (
|
||||||
|
# os.path.exists(
|
||||||
|
# ToolUtil.make_path(P.ModelSetting.get(f"{self.name}_path_config"))
|
||||||
|
# )
|
||||||
|
# is False
|
||||||
|
# ):
|
||||||
|
# shutil.copyfile(
|
||||||
|
# os.path.join(
|
||||||
|
# os.path.dirname(__file__), "files", f"config_{self.name}.yaml"
|
||||||
|
# ),
|
||||||
|
# ToolUtil.make_path(P.ModelSetting.get(f"{self.name}_path_config")),
|
||||||
|
# )
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_default_filename():
|
||||||
|
return MyYoutubeDL.DEFAULT_FILENAME
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_preset_list():
|
||||||
|
return [
|
||||||
|
["bestvideo+bestaudio/best", "최고 화질"],
|
||||||
|
["bestvideo[height<=1080]+bestaudio/best[height<=1080]", "1080p"],
|
||||||
|
["worstvideo+worstaudio/worst", "최저 화질"],
|
||||||
|
["bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]", "최고 화질(mp4)"],
|
||||||
|
[
|
||||||
|
"bestvideo[ext=mp4][height<=1080]+bestaudio[ext=m4a]/best[ext=mp4][height<=1080]",
|
||||||
|
"1080p(mp4)",
|
||||||
|
],
|
||||||
|
["bestvideo[filesize<50M]+bestaudio/best[filesize<50M]", "50MB 미만"],
|
||||||
|
["bestaudio/best", "오디오만"],
|
||||||
|
["_custom", "사용자 정의"],
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_postprocessor_list():
|
||||||
|
return [
|
||||||
|
["", "후처리 안함", None],
|
||||||
|
["mp4", "MP4", "비디오 변환"],
|
||||||
|
["flv", "FLV", "비디오 변환"],
|
||||||
|
["webm", "WebM", "비디오 변환"],
|
||||||
|
["ogg", "Ogg", "비디오 변환"],
|
||||||
|
["mkv", "MKV", "비디오 변환"],
|
||||||
|
["ts", "TS", "비디오 변환"],
|
||||||
|
["avi", "AVI", "비디오 변환"],
|
||||||
|
["wmv", "WMV", "비디오 변환"],
|
||||||
|
["mov", "MOV", "비디오 변환"],
|
||||||
|
["gif", "GIF", "비디오 변환"],
|
||||||
|
["mp3", "MP3", "오디오 추출"],
|
||||||
|
["aac", "AAC", "오디오 추출"],
|
||||||
|
["flac", "FLAC", "오디오 추출"],
|
||||||
|
["m4a", "M4A", "오디오 추출"],
|
||||||
|
["opus", "Opus", "오디오 추출"],
|
||||||
|
["vorbis", "Vorbis", "오디오 추출"],
|
||||||
|
["wav", "WAV", "오디오 추출"],
|
||||||
|
]
|
||||||
18
model.py
Normal file
18
model.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2023/02/25 7:55 PM
|
||||||
|
# @Author : yommi
|
||||||
|
# @Site :
|
||||||
|
# @File : model
|
||||||
|
# @Software: PyCharm
|
||||||
|
# @Path : youtube-dl/model.py
|
||||||
|
|
||||||
|
from .setup import *
|
||||||
|
|
||||||
|
|
||||||
|
class ModelYoutubeDlItem(ModelBase):
|
||||||
|
P = P
|
||||||
|
__tablename__ = "youtube_dl_item"
|
||||||
|
__table_args__ = {"mysql_collate": "utf8_general_ci"}
|
||||||
|
__bind_key__ = P.package_name
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
@@ -8,14 +8,16 @@ from datetime import datetime
|
|||||||
from threading import Thread
|
from threading import Thread
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
import framework.common.celery as celery_shutil
|
from framework import celery as celery_shutil
|
||||||
|
|
||||||
from .plugin import Plugin
|
# from .plugin import Plugin
|
||||||
|
|
||||||
logger = Plugin.logger
|
from .setup import P
|
||||||
ModelSetting = Plugin.ModelSetting
|
|
||||||
|
|
||||||
youtube_dl_package = Plugin.youtube_dl_packages[
|
logger = P.logger
|
||||||
|
ModelSetting = P.ModelSetting
|
||||||
|
|
||||||
|
youtube_dl_package = P.youtube_dl_packages[
|
||||||
int(ModelSetting.get("youtube_dl_package"))
|
int(ModelSetting.get("youtube_dl_package"))
|
||||||
if ModelSetting.get("youtube_dl_package")
|
if ModelSetting.get("youtube_dl_package")
|
||||||
else 1 # LogicMain.db_default["youtube_dl_package"]
|
else 1 # LogicMain.db_default["youtube_dl_package"]
|
||||||
@@ -140,7 +142,9 @@ class MyYoutubeDL:
|
|||||||
}
|
}
|
||||||
ydl_opts.update(self.opts)
|
ydl_opts.update(self.opts)
|
||||||
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
|
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
|
||||||
ydl.download([self.url])
|
logger.debug(self.url)
|
||||||
|
error_code = ydl.download([self.url])
|
||||||
|
logger.debug(error_code)
|
||||||
if self.status in (Status.START, Status.FINISHED): # 다운로드 성공
|
if self.status in (Status.START, Status.FINISHED): # 다운로드 성공
|
||||||
for i in glob(self.temp_path + "/**/*", recursive=True):
|
for i in glob(self.temp_path + "/**/*", recursive=True):
|
||||||
path = i.replace(self.temp_path, self.save_path, 1)
|
path = i.replace(self.temp_path, self.save_path, 1)
|
||||||
@@ -190,12 +194,13 @@ class MyYoutubeDL:
|
|||||||
if http_headers:
|
if http_headers:
|
||||||
ydl_opts["http_headers"] = http_headers
|
ydl_opts["http_headers"] = http_headers
|
||||||
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
|
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
|
||||||
|
# info = ydl.extract_info(url, download=False)
|
||||||
info = ydl.extract_info(url, download=False)
|
info = ydl.extract_info(url, download=False)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error("Exception:%s", error)
|
logger.error("Exception:%s", error)
|
||||||
logger.error(traceback.format_exc())
|
logger.error(traceback.format_exc())
|
||||||
return None
|
return None
|
||||||
return info
|
return ydl.sanitize_info(info)
|
||||||
|
|
||||||
def my_hook(self, data):
|
def my_hook(self, data):
|
||||||
if self.status != Status.STOP:
|
if self.status != Status.STOP:
|
||||||
|
|||||||
346
plugin.py
346
plugin.py
@@ -1,346 +0,0 @@
|
|||||||
import os
|
|
||||||
import traceback
|
|
||||||
import json
|
|
||||||
|
|
||||||
from flask import Blueprint, request, jsonify, abort
|
|
||||||
|
|
||||||
from framework import app, path_data
|
|
||||||
from framework.logger import get_logger
|
|
||||||
from framework.util import Util
|
|
||||||
from framework.common.plugin import (
|
|
||||||
get_model_setting,
|
|
||||||
Logic,
|
|
||||||
default_route_single_module,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Plugin:
|
|
||||||
package_name = __name__.split(".", maxsplit=1)[0]
|
|
||||||
logger = get_logger(package_name)
|
|
||||||
blueprint = Blueprint(
|
|
||||||
package_name,
|
|
||||||
package_name,
|
|
||||||
url_prefix=f"/{package_name}",
|
|
||||||
template_folder=os.path.join(os.path.dirname(__file__), "templates"),
|
|
||||||
static_folder=os.path.join(os.path.dirname(__file__), "static"),
|
|
||||||
)
|
|
||||||
|
|
||||||
# 메뉴 정의
|
|
||||||
menu = {
|
|
||||||
"main": [package_name, "youtube-dl"],
|
|
||||||
"sub": [
|
|
||||||
["setting", "설정"],
|
|
||||||
["download", "다운로드"],
|
|
||||||
["thumbnail", "썸네일 다운로드"],
|
|
||||||
["sub", "자막 다운로드"],
|
|
||||||
["list", "목록"],
|
|
||||||
["log", "로그"],
|
|
||||||
],
|
|
||||||
"category": "vod",
|
|
||||||
}
|
|
||||||
|
|
||||||
plugin_info = {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"name": package_name,
|
|
||||||
"category_name": "vod",
|
|
||||||
"developer": "joyfuI",
|
|
||||||
"description": "유튜브, 네이버TV 등 동영상 사이트에서 동영상 다운로드",
|
|
||||||
"home": f"https://github.com/joyfuI/{package_name}",
|
|
||||||
"more": "",
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelSetting = get_model_setting(package_name, logger)
|
|
||||||
logic = None
|
|
||||||
module_list = None
|
|
||||||
home_module = "list" # 기본모듈
|
|
||||||
|
|
||||||
youtube_dl_packages = ["youtube-dl", "yt-dlp"]
|
|
||||||
|
|
||||||
|
|
||||||
def initialize():
|
|
||||||
try:
|
|
||||||
app.config["SQLALCHEMY_BINDS"][
|
|
||||||
Plugin.package_name
|
|
||||||
] = f"sqlite:///{os.path.join(path_data, 'db', f'{Plugin.package_name}.db')}"
|
|
||||||
Util.save_from_dict_to_json(
|
|
||||||
Plugin.plugin_info, os.path.join(os.path.dirname(__file__), "info.json")
|
|
||||||
)
|
|
||||||
|
|
||||||
# 로드할 모듈 정의
|
|
||||||
from .main import LogicMain
|
|
||||||
|
|
||||||
Plugin.module_list = [LogicMain(Plugin)]
|
|
||||||
|
|
||||||
Plugin.logic = Logic(Plugin)
|
|
||||||
default_route_single_module(Plugin)
|
|
||||||
except Exception as error:
|
|
||||||
Plugin.logger.error("Exception:%s", error)
|
|
||||||
Plugin.logger.error(traceback.format_exc())
|
|
||||||
|
|
||||||
|
|
||||||
# API 명세는 https://github.com/joyfuI/youtube-dl#api
|
|
||||||
@Plugin.blueprint.route("/api/<sub>", methods=["GET", "POST"])
|
|
||||||
def api(sub):
|
|
||||||
from .main import LogicMain
|
|
||||||
from .abort import LogicAbort
|
|
||||||
|
|
||||||
try:
|
|
||||||
Plugin.logger.debug("API: %s, %s", sub, request.values)
|
|
||||||
plugin = request.values.get("plugin")
|
|
||||||
if not plugin: # 요청한 플러그인명이 빈문자열이거나 None면
|
|
||||||
abort(403) # 403 에러(거부)
|
|
||||||
|
|
||||||
# 동영상 정보를 반환하는 API
|
|
||||||
if sub == "info_dict":
|
|
||||||
url = request.values.get("url")
|
|
||||||
ret = {"errorCode": 0, "info_dict": None}
|
|
||||||
if None in (url,):
|
|
||||||
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
|
||||||
if not url.startswith("http"):
|
|
||||||
return LogicAbort.abort(ret, 2) # 잘못된 동영상 주소
|
|
||||||
info_dict = LogicMain.get_info_dict(url, Plugin.ModelSetting.get("proxy"))
|
|
||||||
if info_dict is None:
|
|
||||||
return LogicAbort.abort(ret, 10) # 실패
|
|
||||||
ret["info_dict"] = info_dict
|
|
||||||
|
|
||||||
# 비디오 다운로드 준비를 요청하는 API
|
|
||||||
elif sub == "download":
|
|
||||||
key = request.values.get("key")
|
|
||||||
url = request.values.get("url")
|
|
||||||
filename = request.values.get(
|
|
||||||
"filename", Plugin.ModelSetting.get("default_filename")
|
|
||||||
)
|
|
||||||
save_path = request.values.get(
|
|
||||||
"save_path", Plugin.ModelSetting.get("save_path")
|
|
||||||
)
|
|
||||||
format_code = request.values.get("format", None)
|
|
||||||
preferedformat = request.values.get("preferedformat", None)
|
|
||||||
preferredcodec = request.values.get("preferredcodec", None)
|
|
||||||
preferredquality = request.values.get("preferredquality", 192)
|
|
||||||
dateafter = request.values.get("dateafter", None)
|
|
||||||
playlist = request.values.get("playlist", None)
|
|
||||||
archive = request.values.get("archive", None)
|
|
||||||
start = request.values.get("start", False)
|
|
||||||
cookiefile = request.values.get("cookiefile", None)
|
|
||||||
headers = request.values.get("headers", "null")
|
|
||||||
ret = {"errorCode": 0, "index": None}
|
|
||||||
if None in (key, url):
|
|
||||||
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
|
||||||
if not url.startswith("http"):
|
|
||||||
return LogicAbort.abort(ret, 2) # 잘못된 동영상 주소
|
|
||||||
if preferredcodec not in (
|
|
||||||
None,
|
|
||||||
"best",
|
|
||||||
"mp3",
|
|
||||||
"aac",
|
|
||||||
"flac",
|
|
||||||
"m4a",
|
|
||||||
"opus",
|
|
||||||
"vorbis",
|
|
||||||
"wav",
|
|
||||||
):
|
|
||||||
return LogicAbort.abort(ret, 5) # 허용되지 않은 값이 있음
|
|
||||||
if not filename:
|
|
||||||
filename = LogicMain.get_default_filename()
|
|
||||||
youtube_dl = LogicMain.download(
|
|
||||||
plugin=plugin,
|
|
||||||
url=url,
|
|
||||||
filename=filename,
|
|
||||||
temp_path=Plugin.ModelSetting.get("temp_path"),
|
|
||||||
save_path=save_path,
|
|
||||||
format=format_code,
|
|
||||||
preferedformat=preferedformat,
|
|
||||||
preferredcodec=preferredcodec,
|
|
||||||
preferredquality=preferredquality,
|
|
||||||
dateafter=dateafter,
|
|
||||||
playlist=playlist,
|
|
||||||
archive=archive,
|
|
||||||
proxy=Plugin.ModelSetting.get("proxy"),
|
|
||||||
ffmpeg_path=Plugin.ModelSetting.get("ffmpeg_path"),
|
|
||||||
key=key,
|
|
||||||
cookiefile=cookiefile,
|
|
||||||
headers=json.loads(headers),
|
|
||||||
)
|
|
||||||
if youtube_dl is None:
|
|
||||||
return LogicAbort.abort(ret, 10) # 실패
|
|
||||||
ret["index"] = youtube_dl.index
|
|
||||||
if start:
|
|
||||||
youtube_dl.start()
|
|
||||||
LogicMain.socketio_emit("add", youtube_dl)
|
|
||||||
|
|
||||||
# 썸네일 다운로드 준비를 요청하는 API
|
|
||||||
elif sub == "thumbnail":
|
|
||||||
key = request.values.get("key")
|
|
||||||
url = request.values.get("url")
|
|
||||||
filename = request.values.get(
|
|
||||||
"filename", Plugin.ModelSetting.get("default_filename")
|
|
||||||
)
|
|
||||||
save_path = request.values.get(
|
|
||||||
"save_path", Plugin.ModelSetting.get("save_path")
|
|
||||||
)
|
|
||||||
all_thumbnails = request.values.get("all_thumbnails", False)
|
|
||||||
dateafter = request.values.get("dateafter", None)
|
|
||||||
playlist = request.values.get("playlist", None)
|
|
||||||
archive = request.values.get("archive", None)
|
|
||||||
start = request.values.get("start", False)
|
|
||||||
cookiefile = request.values.get("cookiefile", None)
|
|
||||||
headers = request.values.get("headers", "null")
|
|
||||||
ret = {"errorCode": 0, "index": None}
|
|
||||||
if None in (key, url):
|
|
||||||
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
|
||||||
if not url.startswith("http"):
|
|
||||||
return LogicAbort.abort(ret, 2) # 잘못된 동영상 주소
|
|
||||||
if not filename:
|
|
||||||
filename = LogicMain.get_default_filename()
|
|
||||||
youtube_dl = LogicMain.thumbnail(
|
|
||||||
plugin=plugin,
|
|
||||||
url=url,
|
|
||||||
filename=filename,
|
|
||||||
temp_path=Plugin.ModelSetting.get("temp_path"),
|
|
||||||
save_path=save_path,
|
|
||||||
all_thumbnails=all_thumbnails,
|
|
||||||
dateafter=dateafter,
|
|
||||||
playlist=playlist,
|
|
||||||
archive=archive,
|
|
||||||
proxy=Plugin.ModelSetting.get("proxy"),
|
|
||||||
ffmpeg_path=Plugin.ModelSetting.get("ffmpeg_path"),
|
|
||||||
key=key,
|
|
||||||
cookiefile=cookiefile,
|
|
||||||
headers=json.loads(headers),
|
|
||||||
)
|
|
||||||
if youtube_dl is None:
|
|
||||||
return LogicAbort.abort(ret, 10) # 실패
|
|
||||||
ret["index"] = youtube_dl.index
|
|
||||||
if start:
|
|
||||||
youtube_dl.start()
|
|
||||||
LogicMain.socketio_emit("add", youtube_dl)
|
|
||||||
|
|
||||||
# 자막 다운로드 준비를 요청하는 API
|
|
||||||
elif sub == "sub":
|
|
||||||
key = request.values.get("key")
|
|
||||||
url = request.values.get("url")
|
|
||||||
filename = request.values.get(
|
|
||||||
"filename", Plugin.ModelSetting.get("default_filename")
|
|
||||||
)
|
|
||||||
save_path = request.values.get(
|
|
||||||
"save_path", Plugin.ModelSetting.get("save_path")
|
|
||||||
)
|
|
||||||
all_subs = request.values.get("all_subs", False)
|
|
||||||
sub_lang = request.values.get("sub_lang", "ko")
|
|
||||||
auto_sub = request.values.get("all_subs", False)
|
|
||||||
dateafter = request.values.get("dateafter", None)
|
|
||||||
playlist = request.values.get("playlist", None)
|
|
||||||
archive = request.values.get("archive", None)
|
|
||||||
start = request.values.get("start", False)
|
|
||||||
cookiefile = request.values.get("cookiefile", None)
|
|
||||||
headers = request.values.get("headers", "null")
|
|
||||||
ret = {"errorCode": 0, "index": None}
|
|
||||||
if None in (key, url):
|
|
||||||
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
|
||||||
if not url.startswith("http"):
|
|
||||||
return LogicAbort.abort(ret, 2) # 잘못된 동영상 주소
|
|
||||||
if not filename:
|
|
||||||
filename = LogicMain.get_default_filename()
|
|
||||||
youtube_dl = LogicMain.sub(
|
|
||||||
plugin=plugin,
|
|
||||||
url=url,
|
|
||||||
filename=filename,
|
|
||||||
temp_path=Plugin.ModelSetting.get("temp_path"),
|
|
||||||
save_path=save_path,
|
|
||||||
all_subs=all_subs,
|
|
||||||
sub_lang=sub_lang,
|
|
||||||
auto_sub=auto_sub,
|
|
||||||
dateafter=dateafter,
|
|
||||||
playlist=playlist,
|
|
||||||
archive=archive,
|
|
||||||
proxy=Plugin.ModelSetting.get("proxy"),
|
|
||||||
ffmpeg_path=Plugin.ModelSetting.get("ffmpeg_path"),
|
|
||||||
key=key,
|
|
||||||
cookiefile=cookiefile,
|
|
||||||
headers=json.loads(headers),
|
|
||||||
)
|
|
||||||
if youtube_dl is None:
|
|
||||||
return LogicAbort.abort(ret, 10) # 실패
|
|
||||||
ret["index"] = youtube_dl.index
|
|
||||||
if start:
|
|
||||||
youtube_dl.start()
|
|
||||||
LogicMain.socketio_emit("add", youtube_dl)
|
|
||||||
|
|
||||||
# 다운로드 시작을 요청하는 API
|
|
||||||
elif sub == "start":
|
|
||||||
index = request.values.get("index")
|
|
||||||
key = request.values.get("key")
|
|
||||||
ret = {"errorCode": 0, "status": None}
|
|
||||||
if None in (index, key):
|
|
||||||
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
|
||||||
index = int(index)
|
|
||||||
if not 0 <= index < len(LogicMain.youtube_dl_list):
|
|
||||||
return LogicAbort.abort(ret, 3) # 인덱스 범위를 벗어남
|
|
||||||
youtube_dl = LogicMain.youtube_dl_list[index]
|
|
||||||
if youtube_dl.key != key:
|
|
||||||
return LogicAbort.abort(ret, 4) # 키가 일치하지 않음
|
|
||||||
ret["status"] = youtube_dl.status.name
|
|
||||||
if not youtube_dl.start():
|
|
||||||
return LogicAbort.abort(ret, 10) # 실패
|
|
||||||
|
|
||||||
# 다운로드 중지를 요청하는 API
|
|
||||||
elif sub == "stop":
|
|
||||||
index = request.values.get("index")
|
|
||||||
key = request.values.get("key")
|
|
||||||
ret = {"errorCode": 0, "status": None}
|
|
||||||
if None in (index, key):
|
|
||||||
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
|
||||||
index = int(index)
|
|
||||||
if not 0 <= index < len(LogicMain.youtube_dl_list):
|
|
||||||
return LogicAbort.abort(ret, 3) # 인덱스 범위를 벗어남
|
|
||||||
youtube_dl = LogicMain.youtube_dl_list[index]
|
|
||||||
if youtube_dl.key != key:
|
|
||||||
return LogicAbort.abort(ret, 4) # 키가 일치하지 않음
|
|
||||||
ret["status"] = youtube_dl.status.name
|
|
||||||
if not youtube_dl.stop():
|
|
||||||
return LogicAbort.abort(ret, 10) # 실패
|
|
||||||
|
|
||||||
# 현재 상태를 반환하는 API
|
|
||||||
elif sub == "status":
|
|
||||||
index = request.values.get("index")
|
|
||||||
key = request.values.get("key")
|
|
||||||
ret = {
|
|
||||||
"errorCode": 0,
|
|
||||||
"status": None,
|
|
||||||
"type": None,
|
|
||||||
"start_time": None,
|
|
||||||
"end_time": None,
|
|
||||||
"temp_path": None,
|
|
||||||
"save_path": None,
|
|
||||||
}
|
|
||||||
if None in (index, key):
|
|
||||||
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
|
||||||
index = int(index)
|
|
||||||
if not 0 <= index < len(LogicMain.youtube_dl_list):
|
|
||||||
return LogicAbort.abort(ret, 3) # 인덱스 범위를 벗어남
|
|
||||||
youtube_dl = LogicMain.youtube_dl_list[index]
|
|
||||||
if youtube_dl.key != key:
|
|
||||||
return LogicAbort.abort(ret, 4) # 키가 일치하지 않음
|
|
||||||
ret["status"] = youtube_dl.status.name
|
|
||||||
ret["type"] = youtube_dl.type
|
|
||||||
ret["start_time"] = (
|
|
||||||
youtube_dl.start_time.strftime("%Y-%m-%dT%H:%M:%S")
|
|
||||||
if youtube_dl.start_time is not None
|
|
||||||
else None
|
|
||||||
)
|
|
||||||
ret["end_time"] = (
|
|
||||||
youtube_dl.end_time.strftime("%Y-%m-%dT%H:%M:%S")
|
|
||||||
if youtube_dl.end_time is not None
|
|
||||||
else None
|
|
||||||
)
|
|
||||||
ret["temp_path"] = youtube_dl.temp_path
|
|
||||||
ret["save_path"] = youtube_dl.save_path
|
|
||||||
|
|
||||||
return jsonify(ret)
|
|
||||||
except Exception as error:
|
|
||||||
Plugin.logger.error("Exception:%s", error)
|
|
||||||
Plugin.logger.error(traceback.format_exc())
|
|
||||||
|
|
||||||
|
|
||||||
logger = Plugin.logger
|
|
||||||
initialize()
|
|
||||||
77
setup.py
Normal file
77
setup.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Time : 2023/02/25 7:20 PM
|
||||||
|
# @Author : yommi
|
||||||
|
# @Site :
|
||||||
|
# @File : setup.py
|
||||||
|
# @Software: PyCharm
|
||||||
|
# @Path : youtube-dl/setup.py
|
||||||
|
|
||||||
|
__menu = {
|
||||||
|
"uri": __package__,
|
||||||
|
"name": "유튜브 다운로더",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"uri": "basic",
|
||||||
|
"name": "기본 처리",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"uri": "setting",
|
||||||
|
"name": "설정",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "basic/download",
|
||||||
|
"name": "다운로드",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "download",
|
||||||
|
"name": "다운로드",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"uri": "basic",
|
||||||
|
"name": "다운로드",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{"uri": "thumbnail", "name": "썸네일 다운로드"},
|
||||||
|
{"uri": "sub", "name": "자막 다운로드"},
|
||||||
|
{
|
||||||
|
"uri": "manual",
|
||||||
|
"name": "매뉴얼",
|
||||||
|
"list": [
|
||||||
|
{"uri": "README.md", "name": "README.md"},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "log",
|
||||||
|
"name": "로그",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
setting = {
|
||||||
|
"filepath": __file__,
|
||||||
|
"use_db": True,
|
||||||
|
"use_default_setting": True,
|
||||||
|
"home_module": None,
|
||||||
|
"menu": __menu,
|
||||||
|
"setting_menu": None,
|
||||||
|
"default_route": "normal",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
from plugin import *
|
||||||
|
|
||||||
|
P = create_plugin_instance(setting)
|
||||||
|
P.youtube_dl_packages = ["youtube-dl", "yt-dlp", "youtube-dlc"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
from .mod_basic import ModuleBasic
|
||||||
|
|
||||||
|
P.set_module_list([ModuleBasic])
|
||||||
|
except Exception as e:
|
||||||
|
P.logger.error(f"Exception:{str(e)}")
|
||||||
|
P.logger.error(traceback.format_exc())
|
||||||
|
|
||||||
|
logger = P.logger
|
||||||
49
templates/youtube-dl_basic_download.html
Normal file
49
templates/youtube-dl_basic_download.html
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% macro my_setting_select(id, title, options, col='9', desc=None, value=None) %}
|
||||||
|
{{ macros.setting_top(title) }}
|
||||||
|
<div class="input-group col-sm-{{ col }}">
|
||||||
|
<select id="{{ id }}" name="{{ id }}" class="form-control form-control-sm">
|
||||||
|
{% set ns = namespace(optgroup=none) %}
|
||||||
|
{% for item in options %}
|
||||||
|
{% if ns.optgroup != item[2] %}
|
||||||
|
{% if ns.optgroup is not none %}
|
||||||
|
</optgroup>
|
||||||
|
{% endif %}
|
||||||
|
{% if item[2] is not none %}
|
||||||
|
<optgroup label="{{ item[2] }}">
|
||||||
|
{% endif %}
|
||||||
|
{% set ns.optgroup = item[2] %}
|
||||||
|
{% endif %}
|
||||||
|
{% if value is not none and value == item[0] %}
|
||||||
|
<option value="{{ item[0] }}" selected>{{ item[1] }}</option>
|
||||||
|
{% else %}
|
||||||
|
<option value="{{ item[0] }}">{{ item[1] }}</option>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% if ns.optgroup is not none %}
|
||||||
|
</optgroup>
|
||||||
|
{% endif %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{ macros.setting_bottom(desc) }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<form id="download">
|
||||||
|
{{ macros.setting_input_text('url', 'URL', placeholder='http:// 주소', desc='유튜브, 네이버TV 등 동영상 주소') }}
|
||||||
|
{{ macros.setting_input_text('filename', '파일명', value=arg['filename'], desc='템플릿 규칙은 https://github.com/ytdl-org/youtube-dl/#output-template 참고') }}
|
||||||
|
{{ macros.setting_select('preset', '동영상 포맷 프리셋', arg['preset_list'], col='3') }}
|
||||||
|
{{ macros.setting_input_text('format', '동영상 포맷', desc=['포맷 지정은 https://github.com/ytdl-org/youtube-dl/#format-selection 참고', '빈칸으로 두면 최고 화질로 다운로드합니다.']) }}
|
||||||
|
{{ my_setting_select('postprocessor', '후처리', arg['postprocessor_list'], col='3', desc='다운로드 후 FFmpeg로 후처리합니다.') }}
|
||||||
|
{{ macros.setting_buttons([['download_btn', '다운로드']]) }}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
const package_name = '{{ arg["package_name"] }}';
|
||||||
|
</script>
|
||||||
|
<script src="{{ url_for('.static', filename='%s.js' % arg['template_name']) }}?ver={{ arg['package_version'] }}"></script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
34
templates/youtube-dl_basic_setting.html
Normal file
34
templates/youtube-dl_basic_setting.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{% extends "base.html" %} {% block content %}
|
||||||
|
{{ macros.m_button_group([['globalSettingSaveBtn', '설정 저장'], ['globalOneExecuteBtn', '1회 실행'], ['globalImmediatelyExecuteBtn', '즉시 실행']])}}
|
||||||
|
{{ macros.m_row_start('5') }}
|
||||||
|
{{ macros.m_row_end() }}
|
||||||
|
|
||||||
|
<form id="setting">
|
||||||
|
{{ macros.setting_radio_with_value('youtube_dl_package', 'youtube-dl', arg['package_list'],
|
||||||
|
value=arg['youtube_dl_package'], desc='사용할 youtube-dl 패키지를 선택합니다. 설정 저장 후
|
||||||
|
재시작이 필요합니다.') }}
|
||||||
|
{{ macros.setting_input_text('youtube_dl_version', 'youtube-dl 버전',
|
||||||
|
value=arg['youtube_dl_version'], disabled=True) }}
|
||||||
|
{{
|
||||||
|
macros.setting_input_text_and_buttons('ffmpeg_path', 'FFmpeg 경로', [['ffmpeg_version_btn',
|
||||||
|
'버전확인'], ['ffmpeg_path_btn', '파일 선택']], value=arg['ffmpeg_path'], placeholder='ffmpeg',
|
||||||
|
desc='SJVA에 내장된 버전 말고 원하는 버전을 사용할 수 있습니다.') }} {{
|
||||||
|
macros.setting_input_text_and_buttons('temp_path', '임시 폴더', [['temp_path_btn', '경로 선택']],
|
||||||
|
value=arg['temp_path'], desc='다운로드 파일이 임시로 저장될 폴더입니다.') }} {{
|
||||||
|
macros.setting_input_text_and_buttons('save_path', '저장 폴더', [['save_path_btn', '경로 선택']],
|
||||||
|
value=arg['save_path'], desc='정상적으로 완료된 파일이 이동할 폴더입니다.') }} {{
|
||||||
|
macros.setting_input_text('default_filename', '기본 파일명', value=arg['default_filename'],
|
||||||
|
placeholder=arg['DEFAULT_FILENAME'], desc='템플릿 규칙은
|
||||||
|
https://github.com/ytdl-org/youtube-dl/#output-template 참고') }} {{
|
||||||
|
macros.setting_input_text('proxy', '프록시', value=arg['proxy'], desc=['HTTP/HTTPS/SOCKS를
|
||||||
|
지원합니다. 예) socks5://127.0.0.1:1080/', '빈칸으로 두면 프록시를 사용하지 않습니다.']) }}
|
||||||
|
{# {{ macros.setting_button([['global_setting_save_btn', '저장']]) }}#}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
"use strict"
|
||||||
|
const package_name = '{{ arg["package_name"] }}'
|
||||||
|
</script>
|
||||||
|
<script src="{{ url_for('.static', filename='%s.js' % arg['template_name']) }}?ver={{ arg['package_version'] }}"></script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user