최신 플러그인 구조로 변경
This commit is contained in:
@@ -245,6 +245,10 @@ API를 제공합니다. 다른 플러그인에서 동영상 정보나 다운로
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
v4.0.0
|
||||||
|
|
||||||
|
- 최신 플러그인 구조로 변경
|
||||||
|
|
||||||
v3.1.1
|
v3.1.1
|
||||||
|
|
||||||
- 디폴트 youtube_dl 패키지를 yt-dlp로 변경
|
- 디폴트 youtube_dl 패키지를 yt-dlp로 변경
|
||||||
|
|||||||
@@ -1 +1,7 @@
|
|||||||
from .plugin import blueprint, menu, plugin_info, plugin_load, plugin_unload
|
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
|
||||||
|
|||||||
8
abort.py
Normal file
8
abort.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from flask import jsonify
|
||||||
|
|
||||||
|
|
||||||
|
class LogicAbort:
|
||||||
|
@staticmethod
|
||||||
|
def abort(base, code):
|
||||||
|
base["errorCode"] = code
|
||||||
|
return jsonify(base)
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
{
|
{
|
||||||
"version": "3.1.1",
|
"version": "4.0.0",
|
||||||
"name": "youtube-dl",
|
"name": "youtube-dl",
|
||||||
"category_name": "vod",
|
"category_name": "vod",
|
||||||
"developer": "joyfuI",
|
"developer": "joyfuI",
|
||||||
"description": "유튜브, 네이버TV 등 동영상 사이트에서 동영상 다운로드",
|
"description": "유튜브, 네이버TV 등 동영상 사이트에서 동영상 다운로드",
|
||||||
"home": "https://github.com/joyfuI/youtube-dl",
|
"home": "https://github.com/joyfuI/youtube-dl",
|
||||||
"more": "",
|
"more": ""
|
||||||
"category": "vod"
|
|
||||||
}
|
}
|
||||||
103
logic.py
103
logic.py
@@ -1,103 +0,0 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
import platform
|
|
||||||
import traceback
|
|
||||||
import subprocess
|
|
||||||
import sqlite3
|
|
||||||
|
|
||||||
from framework import db, path_app_root, path_data
|
|
||||||
from framework.logger import get_logger
|
|
||||||
from framework.util import Util
|
|
||||||
|
|
||||||
from .logic_normal import LogicNormal
|
|
||||||
from .model import ModelSetting
|
|
||||||
|
|
||||||
package_name = __name__.split(".", maxsplit=1)[0]
|
|
||||||
logger = get_logger(package_name)
|
|
||||||
|
|
||||||
|
|
||||||
class Logic(object):
|
|
||||||
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": "",
|
|
||||||
}
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def db_init():
|
|
||||||
try:
|
|
||||||
for key, value in Logic.db_default.items():
|
|
||||||
if db.session.query(ModelSetting).filter_by(key=key).count() == 0:
|
|
||||||
db.session.add(ModelSetting(key, value))
|
|
||||||
db.session.commit()
|
|
||||||
Logic.migration()
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s", error)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def plugin_load():
|
|
||||||
try:
|
|
||||||
logger.debug("%s plugin_load", package_name)
|
|
||||||
Logic.db_init()
|
|
||||||
|
|
||||||
# youtube-dl 업데이트
|
|
||||||
youtube_dl = LogicNormal.get_youtube_dl_package(
|
|
||||||
ModelSetting.get("youtube_dl_package")
|
|
||||||
)
|
|
||||||
logger.debug(f"{youtube_dl} upgrade")
|
|
||||||
logger.debug(
|
|
||||||
subprocess.check_output(
|
|
||||||
[sys.executable, "-m", "pip", "install", "--upgrade", youtube_dl],
|
|
||||||
universal_newlines=True,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# 편의를 위해 json 파일 생성
|
|
||||||
from .plugin import plugin_info
|
|
||||||
|
|
||||||
Util.save_from_dict_to_json(
|
|
||||||
plugin_info, os.path.join(os.path.dirname(__file__), "info.json")
|
|
||||||
)
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s", error)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def plugin_unload():
|
|
||||||
try:
|
|
||||||
logger.debug("%s plugin_unload", package_name)
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s", error)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def migration():
|
|
||||||
try:
|
|
||||||
db_version = ModelSetting.get_int("db_version")
|
|
||||||
connect = sqlite3.connect(
|
|
||||||
os.path.join(path_data, "db", f"{package_name}.db")
|
|
||||||
)
|
|
||||||
|
|
||||||
if db_version < 2:
|
|
||||||
logger.debug("youtube-dlc uninstall")
|
|
||||||
logger.debug(
|
|
||||||
subprocess.check_output(
|
|
||||||
[sys.executable, "-m", "pip", "uninstall", "-y", "youtube-dlc"],
|
|
||||||
universal_newlines=True,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
connect.commit()
|
|
||||||
connect.close()
|
|
||||||
ModelSetting.set("db_version", Logic.db_default["db_version"])
|
|
||||||
db.session.flush()
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s", error)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
@@ -1,28 +1,230 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import platform
|
||||||
import traceback
|
import traceback
|
||||||
|
import subprocess
|
||||||
|
import sqlite3
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from flask import jsonify
|
from flask import render_template, jsonify
|
||||||
|
|
||||||
from framework.logger import get_logger
|
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
|
||||||
|
|
||||||
package_name = __name__.split(".", maxsplit=1)[0]
|
logger = Plugin.logger
|
||||||
logger = get_logger(package_name)
|
package_name = Plugin.package_name
|
||||||
|
ModelSetting = Plugin.ModelSetting
|
||||||
|
|
||||||
|
|
||||||
class LogicNormal(object):
|
class LogicMain(LogicModuleBase):
|
||||||
|
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": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, plugin):
|
||||||
|
super(LogicMain, self).__init__(plugin, None)
|
||||||
|
self.name = package_name # 모듈명
|
||||||
|
default_route_socketio(plugin, self)
|
||||||
|
|
||||||
|
def plugin_load(self):
|
||||||
|
try:
|
||||||
|
# youtube-dl 업데이트
|
||||||
|
youtube_dl = Plugin.youtube_dl_packages[
|
||||||
|
int(ModelSetting.get("youtube_dl_package"))
|
||||||
|
]
|
||||||
|
logger.debug(f"{youtube_dl} upgrade")
|
||||||
|
logger.debug(
|
||||||
|
subprocess.check_output(
|
||||||
|
[sys.executable, "-m", "pip", "install", "--upgrade", youtube_dl],
|
||||||
|
universal_newlines=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as error:
|
||||||
|
logger.error("Exception:%s", error)
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
|
||||||
|
def process_menu(self, sub, req):
|
||||||
|
try:
|
||||||
|
arg = {
|
||||||
|
"package_name": package_name,
|
||||||
|
"sub": sub,
|
||||||
|
"template_name": f"{package_name}_{sub}",
|
||||||
|
"package_version": Plugin.plugin_info["version"],
|
||||||
|
}
|
||||||
|
|
||||||
|
if sub == "setting":
|
||||||
|
arg.update(ModelSetting.to_dict())
|
||||||
|
arg["package_list"] = Plugin.youtube_dl_packages
|
||||||
|
arg["youtube_dl_version"] = LogicMain.get_youtube_dl_version()
|
||||||
|
arg["DEFAULT_FILENAME"] = LogicMain.get_default_filename()
|
||||||
|
|
||||||
|
elif sub == "download":
|
||||||
|
default_filename = ModelSetting.get("default_filename")
|
||||||
|
arg["filename"] = (
|
||||||
|
default_filename
|
||||||
|
if default_filename
|
||||||
|
else LogicMain.get_default_filename()
|
||||||
|
)
|
||||||
|
arg["preset_list"] = LogicMain.get_preset_list()
|
||||||
|
arg["postprocessor_list"] = LogicMain.get_postprocessor_list()
|
||||||
|
|
||||||
|
elif sub == "thumbnail":
|
||||||
|
default_filename = ModelSetting.get("default_filename")
|
||||||
|
arg["filename"] = (
|
||||||
|
default_filename
|
||||||
|
if default_filename
|
||||||
|
else LogicMain.get_default_filename()
|
||||||
|
)
|
||||||
|
|
||||||
|
elif sub == "sub":
|
||||||
|
default_filename = ModelSetting.get("default_filename")
|
||||||
|
arg["filename"] = (
|
||||||
|
default_filename
|
||||||
|
if default_filename
|
||||||
|
else LogicMain.get_default_filename()
|
||||||
|
)
|
||||||
|
|
||||||
|
elif sub == "list":
|
||||||
|
pass
|
||||||
|
|
||||||
|
return render_template(f"{package_name}_{sub}.html", arg=arg)
|
||||||
|
except Exception as error:
|
||||||
|
logger.error("Exception:%s", error)
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
return render_template("sample.html", title=f"{package_name} - {sub}")
|
||||||
|
|
||||||
|
def process_ajax(self, sub, req):
|
||||||
|
try:
|
||||||
|
logger.debug("AJAX: %s, %s", sub, req.values)
|
||||||
|
ret = {"ret": "success"}
|
||||||
|
|
||||||
|
if sub == "ffmpeg_version":
|
||||||
|
path = req.form["path"]
|
||||||
|
output = subprocess.check_output([path, "-version"])
|
||||||
|
output = output.decode().replace("\n", "<br>")
|
||||||
|
ret["data"] = output
|
||||||
|
|
||||||
|
elif sub == "download":
|
||||||
|
postprocessor = req.form["postprocessor"]
|
||||||
|
video_convertor, extract_audio = LogicMain.get_postprocessor()
|
||||||
|
preferedformat = None
|
||||||
|
preferredcodec = None
|
||||||
|
preferredquality = None
|
||||||
|
if postprocessor in video_convertor:
|
||||||
|
preferedformat = postprocessor
|
||||||
|
elif postprocessor in extract_audio:
|
||||||
|
preferredcodec = postprocessor
|
||||||
|
preferredquality = 192
|
||||||
|
youtube_dl = LogicMain.download(
|
||||||
|
plugin=package_name,
|
||||||
|
url=req.form["url"],
|
||||||
|
filename=req.form["filename"],
|
||||||
|
temp_path=ModelSetting.get("temp_path"),
|
||||||
|
save_path=ModelSetting.get("save_path"),
|
||||||
|
format=req.form["format"],
|
||||||
|
preferedformat=preferedformat,
|
||||||
|
preferredcodec=preferredcodec,
|
||||||
|
preferredquality=preferredquality,
|
||||||
|
proxy=ModelSetting.get("proxy"),
|
||||||
|
ffmpeg_path=ModelSetting.get("ffmpeg_path")
|
||||||
|
if req.form["ffmpeg_path"] != "ffmpeg"
|
||||||
|
else None,
|
||||||
|
)
|
||||||
|
youtube_dl.start()
|
||||||
|
LogicMain.socketio_emit("add", youtube_dl)
|
||||||
|
|
||||||
|
elif sub == "thumbnail":
|
||||||
|
youtube_dl = LogicMain.thumbnail(
|
||||||
|
plugin=package_name,
|
||||||
|
url=req.form["url"],
|
||||||
|
filename=req.form["filename"],
|
||||||
|
temp_path=ModelSetting.get("temp_path"),
|
||||||
|
save_path=ModelSetting.get("save_path"),
|
||||||
|
all_thumbnails=req.form["all_thumbnails"],
|
||||||
|
proxy=ModelSetting.get("proxy"),
|
||||||
|
ffmpeg_path=ModelSetting.get("ffmpeg_path")
|
||||||
|
if req.form["ffmpeg_path"] != "ffmpeg"
|
||||||
|
else None,
|
||||||
|
)
|
||||||
|
youtube_dl.start()
|
||||||
|
LogicMain.socketio_emit("add", youtube_dl)
|
||||||
|
|
||||||
|
elif sub == "sub":
|
||||||
|
youtube_dl = LogicMain.sub(
|
||||||
|
plugin=package_name,
|
||||||
|
url=req.form["url"],
|
||||||
|
filename=req.form["filename"],
|
||||||
|
temp_path=ModelSetting.get("temp_path"),
|
||||||
|
save_path=ModelSetting.get("save_path"),
|
||||||
|
all_subs=req.form["all_subs"],
|
||||||
|
sub_lang=req.form["sub_lang"],
|
||||||
|
auto_sub=req.form["auto_sub"],
|
||||||
|
proxy=ModelSetting.get("proxy"),
|
||||||
|
ffmpeg_path=ModelSetting.get("ffmpeg_path")
|
||||||
|
if req.form["ffmpeg_path"] != "ffmpeg"
|
||||||
|
else None,
|
||||||
|
)
|
||||||
|
youtube_dl.start()
|
||||||
|
LogicMain.socketio_emit("add", youtube_dl)
|
||||||
|
|
||||||
|
elif sub == "list":
|
||||||
|
ret["data"] = []
|
||||||
|
for i in LogicMain.youtube_dl_list:
|
||||||
|
data = LogicMain.get_data(i)
|
||||||
|
if data is not None:
|
||||||
|
ret["data"].append(data)
|
||||||
|
|
||||||
|
elif sub == "all_stop":
|
||||||
|
for i in LogicMain.youtube_dl_list:
|
||||||
|
i.stop()
|
||||||
|
|
||||||
|
elif sub == "stop":
|
||||||
|
index = int(req.form["index"])
|
||||||
|
LogicMain.youtube_dl_list[index].stop()
|
||||||
|
|
||||||
|
return jsonify(ret)
|
||||||
|
except Exception as error:
|
||||||
|
logger.error("Exception:%s", error)
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
return jsonify({"ret": "danger", "msg": str(error)})
|
||||||
|
|
||||||
|
def migration(self):
|
||||||
|
try:
|
||||||
|
db_version = ModelSetting.get_int("db_version")
|
||||||
|
connect = sqlite3.connect(
|
||||||
|
os.path.join(path_data, "db", f"{package_name}.db")
|
||||||
|
)
|
||||||
|
|
||||||
|
if db_version < 2:
|
||||||
|
logger.debug("youtube-dlc uninstall")
|
||||||
|
logger.debug(
|
||||||
|
subprocess.check_output(
|
||||||
|
[sys.executable, "-m", "pip", "uninstall", "-y", "youtube-dlc"],
|
||||||
|
universal_newlines=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
connect.commit()
|
||||||
|
connect.close()
|
||||||
|
ModelSetting.set("db_version", LogicMain.db_default["db_version"])
|
||||||
|
db.session.flush()
|
||||||
|
except Exception as error:
|
||||||
|
logger.error("Exception:%s", error)
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
|
||||||
youtube_dl_list = []
|
youtube_dl_list = []
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_youtube_dl_package(index=None, import_pkg=False):
|
|
||||||
packages = ["youtube-dl", "yt-dlp"]
|
|
||||||
import_name = ["youtube_dl", "yt_dlp"]
|
|
||||||
if import_pkg:
|
|
||||||
return import_name if index is None else import_name[int(index)]
|
|
||||||
else:
|
|
||||||
return packages if index is None else packages[int(index)]
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_youtube_dl_version():
|
def get_youtube_dl_version():
|
||||||
try:
|
try:
|
||||||
@@ -79,7 +281,7 @@ class LogicNormal(object):
|
|||||||
def get_postprocessor():
|
def get_postprocessor():
|
||||||
video_convertor = []
|
video_convertor = []
|
||||||
extract_audio = []
|
extract_audio = []
|
||||||
for i in LogicNormal.get_postprocessor_list():
|
for i in LogicMain.get_postprocessor_list():
|
||||||
if i[2] == "비디오 변환":
|
if i[2] == "비디오 변환":
|
||||||
video_convertor.append(i[0])
|
video_convertor.append(i[0])
|
||||||
elif i[2] == "오디오 추출":
|
elif i[2] == "오디오 추출":
|
||||||
@@ -136,7 +338,7 @@ class LogicNormal(object):
|
|||||||
plugin, "video", url, filename, temp_path, save_path, opts, dateafter
|
plugin, "video", url, filename, temp_path, save_path, opts, dateafter
|
||||||
)
|
)
|
||||||
youtube_dl.key = kwagrs.get("key")
|
youtube_dl.key = kwagrs.get("key")
|
||||||
LogicNormal.youtube_dl_list.append(youtube_dl) # 리스트 추가
|
LogicMain.youtube_dl_list.append(youtube_dl) # 리스트 추가
|
||||||
return youtube_dl
|
return youtube_dl
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error("Exception:%s", error)
|
logger.error("Exception:%s", error)
|
||||||
@@ -187,7 +389,7 @@ class LogicNormal(object):
|
|||||||
dateafter,
|
dateafter,
|
||||||
)
|
)
|
||||||
youtube_dl.key = kwagrs.get("key")
|
youtube_dl.key = kwagrs.get("key")
|
||||||
LogicNormal.youtube_dl_list.append(youtube_dl) # 리스트 추가
|
LogicMain.youtube_dl_list.append(youtube_dl) # 리스트 추가
|
||||||
return youtube_dl
|
return youtube_dl
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error("Exception:%s", error)
|
logger.error("Exception:%s", error)
|
||||||
@@ -235,7 +437,7 @@ class LogicNormal(object):
|
|||||||
plugin, "subtitle", url, filename, temp_path, save_path, opts, dateafter
|
plugin, "subtitle", url, filename, temp_path, save_path, opts, dateafter
|
||||||
)
|
)
|
||||||
youtube_dl.key = kwagrs.get("key")
|
youtube_dl.key = kwagrs.get("key")
|
||||||
LogicNormal.youtube_dl_list.append(youtube_dl) # 리스트 추가
|
LogicMain.youtube_dl_list.append(youtube_dl) # 리스트 추가
|
||||||
return youtube_dl
|
return youtube_dl
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error("Exception:%s", error)
|
logger.error("Exception:%s", error)
|
||||||
@@ -284,9 +486,7 @@ class LogicNormal(object):
|
|||||||
else ""
|
else ""
|
||||||
)
|
)
|
||||||
data["speed_str"] = (
|
data["speed_str"] = (
|
||||||
LogicNormal.human_readable_size(
|
LogicMain.human_readable_size(youtube_dl.progress_hooks["speed"], "/s")
|
||||||
youtube_dl.progress_hooks["speed"], "/s"
|
|
||||||
)
|
|
||||||
if youtube_dl.progress_hooks["speed"] is not None
|
if youtube_dl.progress_hooks["speed"] is not None
|
||||||
else ""
|
else ""
|
||||||
)
|
)
|
||||||
@@ -303,10 +503,10 @@ class LogicNormal(object):
|
|||||||
youtube_dl.progress_hooks["downloaded_bytes"],
|
youtube_dl.progress_hooks["downloaded_bytes"],
|
||||||
youtube_dl.progress_hooks["total_bytes"],
|
youtube_dl.progress_hooks["total_bytes"],
|
||||||
): # 둘 다 값이 있으면
|
): # 둘 다 값이 있으면
|
||||||
data["downloaded_bytes_str"] = LogicNormal.human_readable_size(
|
data["downloaded_bytes_str"] = LogicMain.human_readable_size(
|
||||||
youtube_dl.progress_hooks["downloaded_bytes"]
|
youtube_dl.progress_hooks["downloaded_bytes"]
|
||||||
)
|
)
|
||||||
data["total_bytes_str"] = LogicNormal.human_readable_size(
|
data["total_bytes_str"] = LogicMain.human_readable_size(
|
||||||
youtube_dl.progress_hooks["total_bytes"]
|
youtube_dl.progress_hooks["total_bytes"]
|
||||||
)
|
)
|
||||||
data[
|
data[
|
||||||
@@ -335,6 +535,7 @@ class LogicNormal(object):
|
|||||||
return f"{size:.1f} YB{suffix}"
|
return f"{size:.1f} YB{suffix}"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def abort(base, code):
|
def socketio_emit(cmd, data):
|
||||||
base["errorCode"] = code
|
socketio.emit(
|
||||||
return jsonify(base)
|
cmd, LogicMain.get_data(data), namespace=f"/{package_name}", broadcast=True
|
||||||
|
)
|
||||||
119
model.py
119
model.py
@@ -1,119 +0,0 @@
|
|||||||
import os
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
from framework import app, db, path_data
|
|
||||||
from framework.logger import get_logger
|
|
||||||
from framework.util import Util
|
|
||||||
|
|
||||||
package_name = __name__.split(".", maxsplit=1)[0]
|
|
||||||
logger = get_logger(package_name)
|
|
||||||
app.config["SQLALCHEMY_BINDS"][package_name] = "sqlite:///%s" % (
|
|
||||||
os.path.join(path_data, "db", f"{package_name}.db")
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ModelSetting(db.Model):
|
|
||||||
__tablename__ = f"{package_name}_setting"
|
|
||||||
__table_args__ = {"mysql_collate": "utf8_general_ci"}
|
|
||||||
__bind_key__ = package_name
|
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
|
||||||
key = db.Column(db.String(100), unique=True, nullable=False)
|
|
||||||
value = db.Column(db.String, nullable=False)
|
|
||||||
|
|
||||||
def __init__(self, key, value):
|
|
||||||
self.key = key
|
|
||||||
self.value = value
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return repr(self.as_dict())
|
|
||||||
|
|
||||||
def as_dict(self):
|
|
||||||
return {x.name: getattr(self, x.name) for x in self.__table__.columns}
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get(key):
|
|
||||||
try:
|
|
||||||
return (
|
|
||||||
db.session.query(ModelSetting).filter_by(key=key).first().value.strip()
|
|
||||||
)
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s %s", error, key)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_int(key):
|
|
||||||
try:
|
|
||||||
return int(ModelSetting.get(key))
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s %s", error, key)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_bool(key):
|
|
||||||
try:
|
|
||||||
return ModelSetting.get(key) == "True"
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s %s", error, key)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def set(key, value):
|
|
||||||
try:
|
|
||||||
item = (
|
|
||||||
db.session.query(ModelSetting)
|
|
||||||
.filter_by(key=key)
|
|
||||||
.with_for_update()
|
|
||||||
.first()
|
|
||||||
)
|
|
||||||
if item is not None:
|
|
||||||
item.value = value.strip()
|
|
||||||
db.session.commit()
|
|
||||||
else:
|
|
||||||
db.session.add(ModelSetting(key, value.strip()))
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s", error)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
logger.error("Error Key:%s Value:%s", key, value)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def to_dict():
|
|
||||||
try:
|
|
||||||
return Util.db_list_to_dict(db.session.query(ModelSetting).all())
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s", error)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def setting_save(req):
|
|
||||||
try:
|
|
||||||
for key, value in req.form.items():
|
|
||||||
if key in ["scheduler", "is_running"]:
|
|
||||||
continue
|
|
||||||
if key.startswith("tmp_"):
|
|
||||||
continue
|
|
||||||
logger.debug("Key:%s Value:%s", key, value)
|
|
||||||
entity = (
|
|
||||||
db.session.query(ModelSetting)
|
|
||||||
.filter_by(key=key)
|
|
||||||
.with_for_update()
|
|
||||||
.first()
|
|
||||||
)
|
|
||||||
entity.value = value
|
|
||||||
db.session.commit()
|
|
||||||
return True
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s", error)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
return False
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_list(key):
|
|
||||||
try:
|
|
||||||
value = ModelSetting.get(key)
|
|
||||||
values = [x.strip().strip() for x in value.replace("\n", "|").split("|")]
|
|
||||||
values = Util.get_list_except_empty(values)
|
|
||||||
return values
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s %s", error, key)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
@@ -8,11 +8,18 @@ from datetime import datetime
|
|||||||
from threading import Thread
|
from threading import Thread
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
from framework.logger import get_logger
|
|
||||||
import framework.common.celery as celery_shutil
|
import framework.common.celery as celery_shutil
|
||||||
|
|
||||||
package_name = __name__.split(".", maxsplit=1)[0]
|
from .plugin import Plugin
|
||||||
logger = get_logger(package_name)
|
|
||||||
|
logger = Plugin.logger
|
||||||
|
ModelSetting = Plugin.ModelSetting
|
||||||
|
|
||||||
|
youtube_dl_package = Plugin.youtube_dl_packages[
|
||||||
|
int(ModelSetting.get("youtube_dl_package"))
|
||||||
|
if ModelSetting.get("youtube_dl_package")
|
||||||
|
else 1 # LogicMain.db_default["youtube_dl_package"]
|
||||||
|
].replace("-", "_")
|
||||||
|
|
||||||
|
|
||||||
class Status(Enum):
|
class Status(Enum):
|
||||||
@@ -29,7 +36,7 @@ class Status(Enum):
|
|||||||
return str_list[self.value]
|
return str_list[self.value]
|
||||||
|
|
||||||
|
|
||||||
class MyYoutubeDL(object):
|
class MyYoutubeDL:
|
||||||
DEFAULT_FILENAME = "%(title)s-%(id)s.%(ext)s"
|
DEFAULT_FILENAME = "%(title)s-%(id)s.%(ext)s"
|
||||||
|
|
||||||
_index = 0
|
_index = 0
|
||||||
@@ -47,8 +54,6 @@ class MyYoutubeDL(object):
|
|||||||
datebefore=None,
|
datebefore=None,
|
||||||
):
|
):
|
||||||
# from youtube_dl.utils import DateRange
|
# from youtube_dl.utils import DateRange
|
||||||
from .plugin import youtube_dl_package
|
|
||||||
|
|
||||||
DateRange = __import__(
|
DateRange = __import__(
|
||||||
f"{youtube_dl_package}.utils", fromlist=["DateRange"]
|
f"{youtube_dl_package}.utils", fromlist=["DateRange"]
|
||||||
).DateRange
|
).DateRange
|
||||||
@@ -106,8 +111,6 @@ class MyYoutubeDL(object):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# import youtube_dl
|
# import youtube_dl
|
||||||
from .plugin import youtube_dl_package
|
|
||||||
|
|
||||||
youtube_dl = __import__(youtube_dl_package)
|
youtube_dl = __import__(youtube_dl_package)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -164,8 +167,6 @@ class MyYoutubeDL(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def get_version():
|
def get_version():
|
||||||
# from youtube_dl.version import __version__
|
# from youtube_dl.version import __version__
|
||||||
from .plugin import youtube_dl_package
|
|
||||||
|
|
||||||
__version__ = __import__(
|
__version__ = __import__(
|
||||||
f"{youtube_dl_package}.version", fromlist=["__version__"]
|
f"{youtube_dl_package}.version", fromlist=["__version__"]
|
||||||
).__version__
|
).__version__
|
||||||
@@ -175,8 +176,6 @@ class MyYoutubeDL(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def get_info_dict(url, proxy=None, cookiefile=None):
|
def get_info_dict(url, proxy=None, cookiefile=None):
|
||||||
# import youtube_dl
|
# import youtube_dl
|
||||||
from .plugin import youtube_dl_package
|
|
||||||
|
|
||||||
youtube_dl = __import__(youtube_dl_package)
|
youtube_dl = __import__(youtube_dl_package)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -220,13 +219,13 @@ class MyYoutubeDL(object):
|
|||||||
|
|
||||||
@status.setter
|
@status.setter
|
||||||
def status(self, value):
|
def status(self, value):
|
||||||
from .plugin import socketio_emit
|
from .main import LogicMain
|
||||||
|
|
||||||
self._status = value
|
self._status = value
|
||||||
socketio_emit("status", self)
|
LogicMain.socketio_emit("status", self)
|
||||||
|
|
||||||
|
|
||||||
class MyLogger(object):
|
class MyLogger:
|
||||||
def debug(self, msg):
|
def debug(self, msg):
|
||||||
if msg.find(" ETA ") != -1:
|
if msg.find(" ETA ") != -1:
|
||||||
# 과도한 로그 방지
|
# 과도한 로그 방지
|
||||||
|
|||||||
376
plugin.py
376
plugin.py
@@ -1,30 +1,21 @@
|
|||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from flask import Blueprint, request, render_template, redirect, jsonify, abort
|
from flask import Blueprint, request, jsonify, abort
|
||||||
from flask_login import login_required
|
|
||||||
from flask_cors import cross_origin
|
|
||||||
|
|
||||||
from framework import check_api, socketio
|
from framework import app, path_data
|
||||||
from framework.logger import get_logger
|
from framework.logger import get_logger
|
||||||
|
from framework.util import Util
|
||||||
from .logic import Logic
|
from framework.common.plugin import (
|
||||||
from .logic_normal import LogicNormal
|
get_model_setting,
|
||||||
from .model import ModelSetting
|
Logic,
|
||||||
|
default_route_single_module,
|
||||||
package_name = __name__.split(".", maxsplit=1)[0]
|
|
||||||
logger = get_logger(package_name)
|
|
||||||
youtube_dl_package = LogicNormal.get_youtube_dl_package(
|
|
||||||
ModelSetting.get("youtube_dl_package")
|
|
||||||
if ModelSetting.get("youtube_dl_package")
|
|
||||||
else Logic.db_default["youtube_dl_package"],
|
|
||||||
import_pkg=True,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
#########################################################
|
|
||||||
# 플러그인 공용
|
class Plugin:
|
||||||
#########################################################
|
package_name = __name__.split(".", maxsplit=1)[0]
|
||||||
|
logger = get_logger(package_name)
|
||||||
blueprint = Blueprint(
|
blueprint = Blueprint(
|
||||||
package_name,
|
package_name,
|
||||||
package_name,
|
package_name,
|
||||||
@@ -33,6 +24,7 @@ blueprint = Blueprint(
|
|||||||
static_folder=os.path.join(os.path.dirname(__file__), "static"),
|
static_folder=os.path.join(os.path.dirname(__file__), "static"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 메뉴 정의
|
||||||
menu = {
|
menu = {
|
||||||
"main": [package_name, "youtube-dl"],
|
"main": [package_name, "youtube-dl"],
|
||||||
"sub": [
|
"sub": [
|
||||||
@@ -47,228 +39,79 @@ menu = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
plugin_info = {
|
plugin_info = {
|
||||||
"version": "3.1.1",
|
"version": "4.0.0",
|
||||||
"name": "youtube-dl",
|
"name": package_name,
|
||||||
"category_name": "vod",
|
"category_name": "vod",
|
||||||
"developer": "joyfuI",
|
"developer": "joyfuI",
|
||||||
"description": "유튜브, 네이버TV 등 동영상 사이트에서 동영상 다운로드",
|
"description": "유튜브, 네이버TV 등 동영상 사이트에서 동영상 다운로드",
|
||||||
"home": "https://github.com/joyfuI/youtube-dl",
|
"home": f"https://github.com/joyfuI/{package_name}",
|
||||||
"more": "",
|
"more": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelSetting = get_model_setting(package_name, logger)
|
||||||
|
logic = None
|
||||||
|
module_list = None
|
||||||
|
home_module = "list" # 기본모듈
|
||||||
|
|
||||||
def plugin_load():
|
youtube_dl_packages = ["youtube-dl", "yt-dlp"]
|
||||||
Logic.plugin_load()
|
|
||||||
|
|
||||||
|
|
||||||
def plugin_unload():
|
def initialize():
|
||||||
Logic.plugin_unload()
|
|
||||||
|
|
||||||
|
|
||||||
#########################################################
|
|
||||||
# WEB Menu
|
|
||||||
#########################################################
|
|
||||||
@blueprint.route("/")
|
|
||||||
def home():
|
|
||||||
return redirect(f"/{package_name}/list")
|
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route("/<sub>")
|
|
||||||
@login_required
|
|
||||||
def first_menu(sub):
|
|
||||||
try:
|
try:
|
||||||
arg = {
|
app.config["SQLALCHEMY_BINDS"][
|
||||||
"package_name": package_name,
|
Plugin.package_name
|
||||||
"template_name": f"{package_name}_{sub}",
|
] = f"sqlite:///{os.path.join(path_data, 'db', f'{Plugin.package_name}.db')}"
|
||||||
"package_version": plugin_info["version"],
|
Util.save_from_dict_to_json(
|
||||||
}
|
Plugin.plugin_info, os.path.join(os.path.dirname(__file__), "info.json")
|
||||||
|
|
||||||
if sub == "setting":
|
|
||||||
arg.update(ModelSetting.to_dict())
|
|
||||||
arg["package_list"] = LogicNormal.get_youtube_dl_package()
|
|
||||||
arg["youtube_dl_version"] = LogicNormal.get_youtube_dl_version()
|
|
||||||
arg["DEFAULT_FILENAME"] = LogicNormal.get_default_filename()
|
|
||||||
return render_template(f"{package_name}_{sub}.html", arg=arg)
|
|
||||||
|
|
||||||
elif sub == "download":
|
|
||||||
default_filename = ModelSetting.get("default_filename")
|
|
||||||
arg["filename"] = (
|
|
||||||
default_filename
|
|
||||||
if default_filename
|
|
||||||
else LogicNormal.get_default_filename()
|
|
||||||
)
|
)
|
||||||
arg["preset_list"] = LogicNormal.get_preset_list()
|
|
||||||
arg["postprocessor_list"] = LogicNormal.get_postprocessor_list()
|
|
||||||
return render_template(f"{package_name}_{sub}.html", arg=arg)
|
|
||||||
|
|
||||||
elif sub == "thumbnail":
|
# 로드할 모듈 정의
|
||||||
default_filename = ModelSetting.get("default_filename")
|
from .main import LogicMain
|
||||||
arg["filename"] = (
|
|
||||||
default_filename
|
|
||||||
if default_filename
|
|
||||||
else LogicNormal.get_default_filename()
|
|
||||||
)
|
|
||||||
return render_template(f"{package_name}_{sub}.html", arg=arg)
|
|
||||||
|
|
||||||
elif sub == "sub":
|
Plugin.module_list = [LogicMain(Plugin)]
|
||||||
default_filename = ModelSetting.get("default_filename")
|
|
||||||
arg["filename"] = (
|
|
||||||
default_filename
|
|
||||||
if default_filename
|
|
||||||
else LogicNormal.get_default_filename()
|
|
||||||
)
|
|
||||||
return render_template(f"{package_name}_{sub}.html", arg=arg)
|
|
||||||
|
|
||||||
elif sub == "list":
|
Plugin.logic = Logic(Plugin)
|
||||||
return render_template(f"{package_name}_{sub}.html", arg=arg)
|
default_route_single_module(Plugin)
|
||||||
|
|
||||||
elif sub == "log":
|
|
||||||
return render_template("log.html", package=package_name)
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error("Exception:%s", error)
|
Plugin.logger.error("Exception:%s", error)
|
||||||
logger.error(traceback.format_exc())
|
Plugin.logger.error(traceback.format_exc())
|
||||||
return render_template("sample.html", title=f"{package_name} - {sub}")
|
|
||||||
|
|
||||||
|
|
||||||
#########################################################
|
|
||||||
# For UI
|
|
||||||
#########################################################
|
|
||||||
@blueprint.route("/ajax/<sub>", methods=["POST"])
|
|
||||||
@login_required
|
|
||||||
def ajax(sub):
|
|
||||||
logger.debug("AJAX %s %s", package_name, sub)
|
|
||||||
try:
|
|
||||||
# 공통 요청
|
|
||||||
if sub == "setting_save":
|
|
||||||
ret = ModelSetting.setting_save(request)
|
|
||||||
if request.form["ffmpeg_path"] == "ffmpeg":
|
|
||||||
ModelSetting.set("ffmpeg_path", "")
|
|
||||||
return jsonify(ret)
|
|
||||||
|
|
||||||
# UI 요청
|
|
||||||
elif sub == "ffmpeg_version":
|
|
||||||
path = request.form["path"]
|
|
||||||
ret = subprocess.check_output([path, "-version"])
|
|
||||||
ret = ret.decode().replace("\n", "<br>")
|
|
||||||
return jsonify(ret)
|
|
||||||
|
|
||||||
elif sub == "download":
|
|
||||||
postprocessor = request.form["postprocessor"]
|
|
||||||
video_convertor, extract_audio = LogicNormal.get_postprocessor()
|
|
||||||
preferedformat = None
|
|
||||||
preferredcodec = None
|
|
||||||
preferredquality = None
|
|
||||||
if postprocessor in video_convertor:
|
|
||||||
preferedformat = postprocessor
|
|
||||||
elif postprocessor in extract_audio:
|
|
||||||
preferredcodec = postprocessor
|
|
||||||
preferredquality = 192
|
|
||||||
youtube_dl = LogicNormal.download(
|
|
||||||
plugin=package_name,
|
|
||||||
url=request.form["url"],
|
|
||||||
filename=request.form["filename"],
|
|
||||||
temp_path=ModelSetting.get("temp_path"),
|
|
||||||
save_path=ModelSetting.get("save_path"),
|
|
||||||
format=request.form["format"],
|
|
||||||
preferedformat=preferedformat,
|
|
||||||
preferredcodec=preferredcodec,
|
|
||||||
preferredquality=preferredquality,
|
|
||||||
proxy=ModelSetting.get("proxy"),
|
|
||||||
ffmpeg_path=ModelSetting.get("ffmpeg_path"),
|
|
||||||
)
|
|
||||||
youtube_dl.start()
|
|
||||||
socketio_emit("add", youtube_dl)
|
|
||||||
return jsonify([])
|
|
||||||
|
|
||||||
elif sub == "thumbnail":
|
|
||||||
youtube_dl = LogicNormal.thumbnail(
|
|
||||||
plugin=package_name,
|
|
||||||
url=request.form["url"],
|
|
||||||
filename=request.form["filename"],
|
|
||||||
temp_path=ModelSetting.get("temp_path"),
|
|
||||||
save_path=ModelSetting.get("save_path"),
|
|
||||||
all_thumbnails=request.form["all_thumbnails"],
|
|
||||||
proxy=ModelSetting.get("proxy"),
|
|
||||||
ffmpeg_path=ModelSetting.get("ffmpeg_path"),
|
|
||||||
)
|
|
||||||
youtube_dl.start()
|
|
||||||
socketio_emit("add", youtube_dl)
|
|
||||||
return jsonify([])
|
|
||||||
|
|
||||||
elif sub == "sub":
|
|
||||||
youtube_dl = LogicNormal.sub(
|
|
||||||
plugin=package_name,
|
|
||||||
url=request.form["url"],
|
|
||||||
filename=request.form["filename"],
|
|
||||||
temp_path=ModelSetting.get("temp_path"),
|
|
||||||
save_path=ModelSetting.get("save_path"),
|
|
||||||
all_subs=request.form["all_subs"],
|
|
||||||
sub_lang=request.form["sub_lang"],
|
|
||||||
auto_sub=request.form["auto_sub"],
|
|
||||||
proxy=ModelSetting.get("proxy"),
|
|
||||||
ffmpeg_path=ModelSetting.get("ffmpeg_path"),
|
|
||||||
)
|
|
||||||
youtube_dl.start()
|
|
||||||
socketio_emit("add", youtube_dl)
|
|
||||||
return jsonify([])
|
|
||||||
|
|
||||||
elif sub == "list":
|
|
||||||
ret = []
|
|
||||||
for i in LogicNormal.youtube_dl_list:
|
|
||||||
data = LogicNormal.get_data(i)
|
|
||||||
if data is not None:
|
|
||||||
ret.append(data)
|
|
||||||
return jsonify(ret)
|
|
||||||
|
|
||||||
elif sub == "all_stop":
|
|
||||||
for i in LogicNormal.youtube_dl_list:
|
|
||||||
i.stop()
|
|
||||||
return jsonify([])
|
|
||||||
|
|
||||||
elif sub == "stop":
|
|
||||||
index = int(request.form["index"])
|
|
||||||
LogicNormal.youtube_dl_list[index].stop()
|
|
||||||
return jsonify([])
|
|
||||||
except Exception as error:
|
|
||||||
logger.error("Exception:%s", error)
|
|
||||||
logger.error(traceback.format_exc())
|
|
||||||
|
|
||||||
|
|
||||||
#########################################################
|
|
||||||
# API
|
|
||||||
#########################################################
|
|
||||||
# API 명세는 https://github.com/joyfuI/youtube-dl#api
|
# API 명세는 https://github.com/joyfuI/youtube-dl#api
|
||||||
@blueprint.route("/api/<sub>", methods=["GET", "POST"])
|
@Plugin.blueprint.route("/api/<sub>", methods=["GET", "POST"])
|
||||||
@cross_origin()
|
|
||||||
@check_api
|
|
||||||
def api(sub):
|
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")
|
plugin = request.values.get("plugin")
|
||||||
logger.debug("API %s %s: %s", package_name, sub, plugin)
|
|
||||||
if not plugin: # 요청한 플러그인명이 빈문자열이거나 None면
|
if not plugin: # 요청한 플러그인명이 빈문자열이거나 None면
|
||||||
abort(403) # 403 에러(거부)
|
abort(403) # 403 에러(거부)
|
||||||
try:
|
|
||||||
# 동영상 정보를 반환하는 API
|
# 동영상 정보를 반환하는 API
|
||||||
if sub == "info_dict":
|
if sub == "info_dict":
|
||||||
url = request.values.get("url")
|
url = request.values.get("url")
|
||||||
ret = {"errorCode": 0, "info_dict": None}
|
ret = {"errorCode": 0, "info_dict": None}
|
||||||
if None in (url,):
|
if None in (url,):
|
||||||
return LogicNormal.abort(ret, 1) # 필수 요청 변수가 없음
|
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
||||||
if not url.startswith("http"):
|
if not url.startswith("http"):
|
||||||
return LogicNormal.abort(ret, 2) # 잘못된 동영상 주소
|
return LogicAbort.abort(ret, 2) # 잘못된 동영상 주소
|
||||||
info_dict = LogicNormal.get_info_dict(url, ModelSetting.get("proxy"))
|
info_dict = LogicMain.get_info_dict(url, Plugin.ModelSetting.get("proxy"))
|
||||||
if info_dict is None:
|
if info_dict is None:
|
||||||
return LogicNormal.abort(ret, 10) # 실패
|
return LogicAbort.abort(ret, 10) # 실패
|
||||||
ret["info_dict"] = info_dict
|
ret["info_dict"] = info_dict
|
||||||
return jsonify(ret)
|
|
||||||
|
|
||||||
# 비디오 다운로드 준비를 요청하는 API
|
# 비디오 다운로드 준비를 요청하는 API
|
||||||
elif sub == "download":
|
elif sub == "download":
|
||||||
key = request.values.get("key")
|
key = request.values.get("key")
|
||||||
url = request.values.get("url")
|
url = request.values.get("url")
|
||||||
filename = request.values.get(
|
filename = request.values.get(
|
||||||
"filename", ModelSetting.get("default_filename")
|
"filename", Plugin.ModelSetting.get("default_filename")
|
||||||
|
)
|
||||||
|
save_path = request.values.get(
|
||||||
|
"save_path", Plugin.ModelSetting.get("save_path")
|
||||||
)
|
)
|
||||||
save_path = request.values.get("save_path", ModelSetting.get("save_path"))
|
|
||||||
format_code = request.values.get("format", None)
|
format_code = request.values.get("format", None)
|
||||||
preferedformat = request.values.get("preferedformat", None)
|
preferedformat = request.values.get("preferedformat", None)
|
||||||
preferredcodec = request.values.get("preferredcodec", None)
|
preferredcodec = request.values.get("preferredcodec", None)
|
||||||
@@ -280,9 +123,9 @@ def api(sub):
|
|||||||
cookiefile = request.values.get("cookiefile", None)
|
cookiefile = request.values.get("cookiefile", None)
|
||||||
ret = {"errorCode": 0, "index": None}
|
ret = {"errorCode": 0, "index": None}
|
||||||
if None in (key, url):
|
if None in (key, url):
|
||||||
return LogicNormal.abort(ret, 1) # 필수 요청 변수가 없음
|
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
||||||
if not url.startswith("http"):
|
if not url.startswith("http"):
|
||||||
return LogicNormal.abort(ret, 2) # 잘못된 동영상 주소
|
return LogicAbort.abort(ret, 2) # 잘못된 동영상 주소
|
||||||
if preferredcodec not in (
|
if preferredcodec not in (
|
||||||
None,
|
None,
|
||||||
"best",
|
"best",
|
||||||
@@ -294,14 +137,14 @@ def api(sub):
|
|||||||
"vorbis",
|
"vorbis",
|
||||||
"wav",
|
"wav",
|
||||||
):
|
):
|
||||||
return LogicNormal.abort(ret, 5) # 허용되지 않은 값이 있음
|
return LogicAbort.abort(ret, 5) # 허용되지 않은 값이 있음
|
||||||
if not filename:
|
if not filename:
|
||||||
filename = LogicNormal.get_default_filename()
|
filename = LogicMain.get_default_filename()
|
||||||
youtube_dl = LogicNormal.download(
|
youtube_dl = LogicMain.download(
|
||||||
plugin=plugin,
|
plugin=plugin,
|
||||||
url=url,
|
url=url,
|
||||||
filename=filename,
|
filename=filename,
|
||||||
temp_path=ModelSetting.get("temp_path"),
|
temp_path=Plugin.ModelSetting.get("temp_path"),
|
||||||
save_path=save_path,
|
save_path=save_path,
|
||||||
format=format_code,
|
format=format_code,
|
||||||
preferedformat=preferedformat,
|
preferedformat=preferedformat,
|
||||||
@@ -310,27 +153,28 @@ def api(sub):
|
|||||||
dateafter=dateafter,
|
dateafter=dateafter,
|
||||||
playlist=playlist,
|
playlist=playlist,
|
||||||
archive=archive,
|
archive=archive,
|
||||||
proxy=ModelSetting.get("proxy"),
|
proxy=Plugin.ModelSetting.get("proxy"),
|
||||||
ffmpeg_path=ModelSetting.get("ffmpeg_path"),
|
ffmpeg_path=Plugin.ModelSetting.get("ffmpeg_path"),
|
||||||
key=key,
|
key=key,
|
||||||
cookiefile=cookiefile,
|
cookiefile=cookiefile,
|
||||||
)
|
)
|
||||||
if youtube_dl is None:
|
if youtube_dl is None:
|
||||||
return LogicNormal.abort(ret, 10) # 실패
|
return LogicAbort.abort(ret, 10) # 실패
|
||||||
ret["index"] = youtube_dl.index
|
ret["index"] = youtube_dl.index
|
||||||
if start:
|
if start:
|
||||||
youtube_dl.start()
|
youtube_dl.start()
|
||||||
socketio_emit("add", youtube_dl)
|
LogicMain.socketio_emit("add", youtube_dl)
|
||||||
return jsonify(ret)
|
|
||||||
|
|
||||||
# 썸네일 다운로드 준비를 요청하는 API
|
# 썸네일 다운로드 준비를 요청하는 API
|
||||||
elif sub == "thumbnail":
|
elif sub == "thumbnail":
|
||||||
key = request.values.get("key")
|
key = request.values.get("key")
|
||||||
url = request.values.get("url")
|
url = request.values.get("url")
|
||||||
filename = request.values.get(
|
filename = request.values.get(
|
||||||
"filename", ModelSetting.get("default_filename")
|
"filename", Plugin.ModelSetting.get("default_filename")
|
||||||
|
)
|
||||||
|
save_path = request.values.get(
|
||||||
|
"save_path", Plugin.ModelSetting.get("save_path")
|
||||||
)
|
)
|
||||||
save_path = request.values.get("save_path", ModelSetting.get("save_path"))
|
|
||||||
all_thumbnails = request.values.get("all_thumbnails", False)
|
all_thumbnails = request.values.get("all_thumbnails", False)
|
||||||
dateafter = request.values.get("dateafter", None)
|
dateafter = request.values.get("dateafter", None)
|
||||||
playlist = request.values.get("playlist", None)
|
playlist = request.values.get("playlist", None)
|
||||||
@@ -339,42 +183,43 @@ def api(sub):
|
|||||||
cookiefile = request.values.get("cookiefile", None)
|
cookiefile = request.values.get("cookiefile", None)
|
||||||
ret = {"errorCode": 0, "index": None}
|
ret = {"errorCode": 0, "index": None}
|
||||||
if None in (key, url):
|
if None in (key, url):
|
||||||
return LogicNormal.abort(ret, 1) # 필수 요청 변수가 없음
|
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
||||||
if not url.startswith("http"):
|
if not url.startswith("http"):
|
||||||
return LogicNormal.abort(ret, 2) # 잘못된 동영상 주소
|
return LogicAbort.abort(ret, 2) # 잘못된 동영상 주소
|
||||||
if not filename:
|
if not filename:
|
||||||
filename = LogicNormal.get_default_filename()
|
filename = LogicMain.get_default_filename()
|
||||||
youtube_dl = LogicNormal.thumbnail(
|
youtube_dl = LogicMain.thumbnail(
|
||||||
plugin=plugin,
|
plugin=plugin,
|
||||||
url=url,
|
url=url,
|
||||||
filename=filename,
|
filename=filename,
|
||||||
temp_path=ModelSetting.get("temp_path"),
|
temp_path=Plugin.ModelSetting.get("temp_path"),
|
||||||
save_path=save_path,
|
save_path=save_path,
|
||||||
all_thumbnails=all_thumbnails,
|
all_thumbnails=all_thumbnails,
|
||||||
dateafter=dateafter,
|
dateafter=dateafter,
|
||||||
playlist=playlist,
|
playlist=playlist,
|
||||||
archive=archive,
|
archive=archive,
|
||||||
proxy=ModelSetting.get("proxy"),
|
proxy=Plugin.ModelSetting.get("proxy"),
|
||||||
ffmpeg_path=ModelSetting.get("ffmpeg_path"),
|
ffmpeg_path=Plugin.ModelSetting.get("ffmpeg_path"),
|
||||||
key=key,
|
key=key,
|
||||||
cookiefile=cookiefile,
|
cookiefile=cookiefile,
|
||||||
)
|
)
|
||||||
if youtube_dl is None:
|
if youtube_dl is None:
|
||||||
return LogicNormal.abort(ret, 10) # 실패
|
return LogicAbort.abort(ret, 10) # 실패
|
||||||
ret["index"] = youtube_dl.index
|
ret["index"] = youtube_dl.index
|
||||||
if start:
|
if start:
|
||||||
youtube_dl.start()
|
youtube_dl.start()
|
||||||
socketio_emit("add", youtube_dl)
|
LogicMain.socketio_emit("add", youtube_dl)
|
||||||
return jsonify(ret)
|
|
||||||
|
|
||||||
# 자막 다운로드 준비를 요청하는 API
|
# 자막 다운로드 준비를 요청하는 API
|
||||||
elif sub == "sub":
|
elif sub == "sub":
|
||||||
key = request.values.get("key")
|
key = request.values.get("key")
|
||||||
url = request.values.get("url")
|
url = request.values.get("url")
|
||||||
filename = request.values.get(
|
filename = request.values.get(
|
||||||
"filename", ModelSetting.get("default_filename")
|
"filename", Plugin.ModelSetting.get("default_filename")
|
||||||
|
)
|
||||||
|
save_path = request.values.get(
|
||||||
|
"save_path", Plugin.ModelSetting.get("save_path")
|
||||||
)
|
)
|
||||||
save_path = request.values.get("save_path", ModelSetting.get("save_path"))
|
|
||||||
all_subs = request.values.get("all_subs", False)
|
all_subs = request.values.get("all_subs", False)
|
||||||
sub_lang = request.values.get("sub_lang", "ko")
|
sub_lang = request.values.get("sub_lang", "ko")
|
||||||
auto_sub = request.values.get("all_subs", False)
|
auto_sub = request.values.get("all_subs", False)
|
||||||
@@ -385,16 +230,16 @@ def api(sub):
|
|||||||
cookiefile = request.values.get("cookiefile", None)
|
cookiefile = request.values.get("cookiefile", None)
|
||||||
ret = {"errorCode": 0, "index": None}
|
ret = {"errorCode": 0, "index": None}
|
||||||
if None in (key, url):
|
if None in (key, url):
|
||||||
return LogicNormal.abort(ret, 1) # 필수 요청 변수가 없음
|
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
||||||
if not url.startswith("http"):
|
if not url.startswith("http"):
|
||||||
return LogicNormal.abort(ret, 2) # 잘못된 동영상 주소
|
return LogicAbort.abort(ret, 2) # 잘못된 동영상 주소
|
||||||
if not filename:
|
if not filename:
|
||||||
filename = LogicNormal.get_default_filename()
|
filename = LogicMain.get_default_filename()
|
||||||
youtube_dl = LogicNormal.sub(
|
youtube_dl = LogicMain.sub(
|
||||||
plugin=plugin,
|
plugin=plugin,
|
||||||
url=url,
|
url=url,
|
||||||
filename=filename,
|
filename=filename,
|
||||||
temp_path=ModelSetting.get("temp_path"),
|
temp_path=Plugin.ModelSetting.get("temp_path"),
|
||||||
save_path=save_path,
|
save_path=save_path,
|
||||||
all_subs=all_subs,
|
all_subs=all_subs,
|
||||||
sub_lang=sub_lang,
|
sub_lang=sub_lang,
|
||||||
@@ -402,18 +247,17 @@ def api(sub):
|
|||||||
dateafter=dateafter,
|
dateafter=dateafter,
|
||||||
playlist=playlist,
|
playlist=playlist,
|
||||||
archive=archive,
|
archive=archive,
|
||||||
proxy=ModelSetting.get("proxy"),
|
proxy=Plugin.ModelSetting.get("proxy"),
|
||||||
ffmpeg_path=ModelSetting.get("ffmpeg_path"),
|
ffmpeg_path=Plugin.ModelSetting.get("ffmpeg_path"),
|
||||||
key=key,
|
key=key,
|
||||||
cookiefile=cookiefile,
|
cookiefile=cookiefile,
|
||||||
)
|
)
|
||||||
if youtube_dl is None:
|
if youtube_dl is None:
|
||||||
return LogicNormal.abort(ret, 10) # 실패
|
return LogicAbort.abort(ret, 10) # 실패
|
||||||
ret["index"] = youtube_dl.index
|
ret["index"] = youtube_dl.index
|
||||||
if start:
|
if start:
|
||||||
youtube_dl.start()
|
youtube_dl.start()
|
||||||
socketio_emit("add", youtube_dl)
|
LogicMain.socketio_emit("add", youtube_dl)
|
||||||
return jsonify(ret)
|
|
||||||
|
|
||||||
# 다운로드 시작을 요청하는 API
|
# 다운로드 시작을 요청하는 API
|
||||||
elif sub == "start":
|
elif sub == "start":
|
||||||
@@ -421,17 +265,16 @@ def api(sub):
|
|||||||
key = request.values.get("key")
|
key = request.values.get("key")
|
||||||
ret = {"errorCode": 0, "status": None}
|
ret = {"errorCode": 0, "status": None}
|
||||||
if None in (index, key):
|
if None in (index, key):
|
||||||
return LogicNormal.abort(ret, 1) # 필수 요청 변수가 없음
|
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
||||||
index = int(index)
|
index = int(index)
|
||||||
if not 0 <= index < len(LogicNormal.youtube_dl_list):
|
if not 0 <= index < len(LogicMain.youtube_dl_list):
|
||||||
return LogicNormal.abort(ret, 3) # 인덱스 범위를 벗어남
|
return LogicAbort.abort(ret, 3) # 인덱스 범위를 벗어남
|
||||||
youtube_dl = LogicNormal.youtube_dl_list[index]
|
youtube_dl = LogicMain.youtube_dl_list[index]
|
||||||
if youtube_dl.key != key:
|
if youtube_dl.key != key:
|
||||||
return LogicNormal.abort(ret, 4) # 키가 일치하지 않음
|
return LogicAbort.abort(ret, 4) # 키가 일치하지 않음
|
||||||
ret["status"] = youtube_dl.status.name
|
ret["status"] = youtube_dl.status.name
|
||||||
if not youtube_dl.start():
|
if not youtube_dl.start():
|
||||||
return LogicNormal.abort(ret, 10) # 실패
|
return LogicAbort.abort(ret, 10) # 실패
|
||||||
return jsonify(ret)
|
|
||||||
|
|
||||||
# 다운로드 중지를 요청하는 API
|
# 다운로드 중지를 요청하는 API
|
||||||
elif sub == "stop":
|
elif sub == "stop":
|
||||||
@@ -439,17 +282,16 @@ def api(sub):
|
|||||||
key = request.values.get("key")
|
key = request.values.get("key")
|
||||||
ret = {"errorCode": 0, "status": None}
|
ret = {"errorCode": 0, "status": None}
|
||||||
if None in (index, key):
|
if None in (index, key):
|
||||||
return LogicNormal.abort(ret, 1) # 필수 요청 변수가 없음
|
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
||||||
index = int(index)
|
index = int(index)
|
||||||
if not 0 <= index < len(LogicNormal.youtube_dl_list):
|
if not 0 <= index < len(LogicMain.youtube_dl_list):
|
||||||
return LogicNormal.abort(ret, 3) # 인덱스 범위를 벗어남
|
return LogicAbort.abort(ret, 3) # 인덱스 범위를 벗어남
|
||||||
youtube_dl = LogicNormal.youtube_dl_list[index]
|
youtube_dl = LogicMain.youtube_dl_list[index]
|
||||||
if youtube_dl.key != key:
|
if youtube_dl.key != key:
|
||||||
return LogicNormal.abort(ret, 4) # 키가 일치하지 않음
|
return LogicAbort.abort(ret, 4) # 키가 일치하지 않음
|
||||||
ret["status"] = youtube_dl.status.name
|
ret["status"] = youtube_dl.status.name
|
||||||
if not youtube_dl.stop():
|
if not youtube_dl.stop():
|
||||||
return LogicNormal.abort(ret, 10) # 실패
|
return LogicAbort.abort(ret, 10) # 실패
|
||||||
return jsonify(ret)
|
|
||||||
|
|
||||||
# 현재 상태를 반환하는 API
|
# 현재 상태를 반환하는 API
|
||||||
elif sub == "status":
|
elif sub == "status":
|
||||||
@@ -465,13 +307,13 @@ def api(sub):
|
|||||||
"save_path": None,
|
"save_path": None,
|
||||||
}
|
}
|
||||||
if None in (index, key):
|
if None in (index, key):
|
||||||
return LogicNormal.abort(ret, 1) # 필수 요청 변수가 없음
|
return LogicAbort.abort(ret, 1) # 필수 요청 변수가 없음
|
||||||
index = int(index)
|
index = int(index)
|
||||||
if not 0 <= index < len(LogicNormal.youtube_dl_list):
|
if not 0 <= index < len(LogicMain.youtube_dl_list):
|
||||||
return LogicNormal.abort(ret, 3) # 인덱스 범위를 벗어남
|
return LogicAbort.abort(ret, 3) # 인덱스 범위를 벗어남
|
||||||
youtube_dl = LogicNormal.youtube_dl_list[index]
|
youtube_dl = LogicMain.youtube_dl_list[index]
|
||||||
if youtube_dl.key != key:
|
if youtube_dl.key != key:
|
||||||
return LogicNormal.abort(ret, 4) # 키가 일치하지 않음
|
return LogicAbort.abort(ret, 4) # 키가 일치하지 않음
|
||||||
ret["status"] = youtube_dl.status.name
|
ret["status"] = youtube_dl.status.name
|
||||||
ret["type"] = youtube_dl.type
|
ret["type"] = youtube_dl.type
|
||||||
ret["start_time"] = (
|
ret["start_time"] = (
|
||||||
@@ -486,18 +328,12 @@ def api(sub):
|
|||||||
)
|
)
|
||||||
ret["temp_path"] = youtube_dl.temp_path
|
ret["temp_path"] = youtube_dl.temp_path
|
||||||
ret["save_path"] = youtube_dl.save_path
|
ret["save_path"] = youtube_dl.save_path
|
||||||
|
|
||||||
return jsonify(ret)
|
return jsonify(ret)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
logger.error("Exception:%s", error)
|
Plugin.logger.error("Exception:%s", error)
|
||||||
logger.error(traceback.format_exc())
|
Plugin.logger.error(traceback.format_exc())
|
||||||
abort(500) # 500 에러(서버 오류)
|
|
||||||
abort(404) # 404 에러(페이지 없음)
|
|
||||||
|
|
||||||
|
|
||||||
#########################################################
|
logger = Plugin.logger
|
||||||
# socketio
|
initialize()
|
||||||
#########################################################
|
|
||||||
def socketio_emit(cmd, data):
|
|
||||||
socketio.emit(
|
|
||||||
cmd, LogicNormal.get_data(data), namespace=f"/{package_name}", broadcast=True
|
|
||||||
)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user