2022.01.31 anilife 버그 픽스 (.03. 기타)
This commit is contained in:
1
lib/plugin/__init__.py
Normal file
1
lib/plugin/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .ffmpeg_queue import FfmpegQueueEntity, FfmpegQueue
|
||||
293
lib/plugin/ffmpeg_queue.py
Normal file
293
lib/plugin/ffmpeg_queue.py
Normal file
@@ -0,0 +1,293 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#########################################################
|
||||
# python
|
||||
import os, sys, traceback
|
||||
import threading, time
|
||||
from datetime import datetime
|
||||
import abc
|
||||
from framework import py_queue
|
||||
|
||||
|
||||
# third-party
|
||||
# sjva 공용
|
||||
#########################################################
|
||||
|
||||
|
||||
class FfmpegQueueEntity(abc.ABCMeta("ABC", (object,), {"__slots__": ()})):
|
||||
def __init__(self, P, module_logic, info):
|
||||
self.P = P
|
||||
self.module_logic = module_logic
|
||||
self.entity_id = -1 # FfmpegQueueEntity.static_index
|
||||
self.info = info
|
||||
self.url = None
|
||||
self.ffmpeg_status = -1
|
||||
self.ffmpeg_status_kor = "대기중"
|
||||
self.ffmpeg_percent = 0
|
||||
self.ffmpeg_arg = None
|
||||
self.cancel = False
|
||||
self.created_time = datetime.now().strftime("%m-%d %H:%M:%S")
|
||||
self.savepath = None
|
||||
self.filename = None
|
||||
self.filepath = None
|
||||
self.quality = None
|
||||
self.headers = None
|
||||
# FfmpegQueueEntity.static_index += 1
|
||||
# FfmpegQueueEntity.entity_list.append(self)
|
||||
|
||||
def get_video_url(self):
|
||||
return self.url
|
||||
|
||||
def get_video_filepath(self):
|
||||
return self.filepath
|
||||
|
||||
@abc.abstractmethod
|
||||
def refresh_status(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def info_dict(self, tmp):
|
||||
pass
|
||||
|
||||
def download_completed(self):
|
||||
pass
|
||||
|
||||
def as_dict(self):
|
||||
tmp = {}
|
||||
tmp["entity_id"] = self.entity_id
|
||||
tmp["url"] = self.url
|
||||
tmp["ffmpeg_status"] = self.ffmpeg_status
|
||||
tmp["ffmpeg_status_kor"] = self.ffmpeg_status_kor
|
||||
tmp["ffmpeg_percent"] = self.ffmpeg_percent
|
||||
tmp["ffmpeg_arg"] = self.ffmpeg_arg
|
||||
tmp["cancel"] = self.cancel
|
||||
tmp["created_time"] = self.created_time # .strftime('%m-%d %H:%M:%S')
|
||||
tmp["savepath"] = self.savepath
|
||||
tmp["filename"] = self.filename
|
||||
tmp["filepath"] = self.filepath
|
||||
tmp["quality"] = self.quality
|
||||
# tmp['current_speed'] = self.ffmpeg_arg['current_speed'] if self.ffmpeg_arg is not None else ''
|
||||
tmp = self.info_dict(tmp)
|
||||
return tmp
|
||||
|
||||
|
||||
class FfmpegQueue(object):
|
||||
def __init__(self, P, max_ffmpeg_count):
|
||||
self.P = P
|
||||
self.static_index = 1
|
||||
self.entity_list = []
|
||||
self.current_ffmpeg_count = 0
|
||||
self.download_queue = None
|
||||
self.download_thread = None
|
||||
self.max_ffmpeg_count = max_ffmpeg_count
|
||||
if self.max_ffmpeg_count is None or self.max_ffmpeg_count == "":
|
||||
self.max_ffmpeg_count = 1
|
||||
|
||||
def queue_start(self):
|
||||
try:
|
||||
if self.download_queue is None:
|
||||
self.download_queue = py_queue.Queue()
|
||||
if self.download_thread is None:
|
||||
self.download_thread = threading.Thread(
|
||||
target=self.download_thread_function, args=()
|
||||
)
|
||||
self.download_thread.daemon = True
|
||||
self.download_thread.start()
|
||||
except Exception as exception:
|
||||
self.P.logger.error("Exception:%s", exception)
|
||||
self.P.logger.error(traceback.format_exc())
|
||||
|
||||
def download_thread_function(self):
|
||||
while True:
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
if self.current_ffmpeg_count < self.max_ffmpeg_count:
|
||||
break
|
||||
time.sleep(5)
|
||||
except Exception as exception:
|
||||
self.P.logger.error("Exception:%s", exception)
|
||||
self.P.logger.error(traceback.format_exc())
|
||||
self.P.logger.error(
|
||||
"current_ffmpeg_count : %s", self.current_ffmpeg_count
|
||||
)
|
||||
self.P.logger.error(
|
||||
"max_ffmpeg_count : %s", self.max_ffmpeg_count
|
||||
)
|
||||
break
|
||||
entity = self.download_queue.get()
|
||||
if entity.cancel:
|
||||
continue
|
||||
|
||||
# from .logic_ani24 import LogicAni24
|
||||
# entity.url = LogicAni24.get_video_url(entity.info['code'])
|
||||
video_url = entity.get_video_url()
|
||||
if video_url is None:
|
||||
entity.ffmpeg_status_kor = "URL실패"
|
||||
entity.refresh_status()
|
||||
# plugin.socketio_list_refresh()
|
||||
continue
|
||||
|
||||
import ffmpeg
|
||||
|
||||
# max_pf_count = 0
|
||||
# save_path = ModelSetting.get('download_path')
|
||||
# if ModelSetting.get('auto_make_folder') == 'True':
|
||||
# program_path = os.path.join(save_path, entity.info['filename'].split('.')[0])
|
||||
# save_path = program_path
|
||||
# try:
|
||||
# if not os.path.exists(save_path):
|
||||
# os.makedirs(save_path)
|
||||
# except:
|
||||
# logger.debug('program path make fail!!')
|
||||
# 파일 존재여부 체크
|
||||
filepath = entity.get_video_filepath()
|
||||
if os.path.exists(filepath):
|
||||
entity.ffmpeg_status_kor = "파일 있음"
|
||||
entity.ffmpeg_percent = 100
|
||||
entity.refresh_status()
|
||||
# plugin.socketio_list_refresh()
|
||||
continue
|
||||
dirname = os.path.dirname(filepath)
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
f = ffmpeg.Ffmpeg(
|
||||
video_url,
|
||||
os.path.basename(filepath),
|
||||
plugin_id=entity.entity_id,
|
||||
listener=self.ffmpeg_listener,
|
||||
call_plugin=self.P.package_name,
|
||||
save_path=dirname,
|
||||
headers=entity.headers,
|
||||
)
|
||||
f.start()
|
||||
self.current_ffmpeg_count += 1
|
||||
self.download_queue.task_done()
|
||||
except Exception as exception:
|
||||
self.P.logger.error("Exception:%s", exception)
|
||||
self.P.logger.error(traceback.format_exc())
|
||||
|
||||
def ffmpeg_listener(self, **arg):
|
||||
import ffmpeg
|
||||
|
||||
entity = self.get_entity_by_entity_id(arg["plugin_id"])
|
||||
if entity is None:
|
||||
return
|
||||
if arg["type"] == "status_change":
|
||||
if arg["status"] == ffmpeg.Status.DOWNLOADING:
|
||||
pass
|
||||
elif arg["status"] == ffmpeg.Status.COMPLETED:
|
||||
entity.download_completed()
|
||||
elif arg["status"] == ffmpeg.Status.READY:
|
||||
pass
|
||||
elif arg["type"] == "last":
|
||||
self.current_ffmpeg_count += -1
|
||||
elif arg["type"] == "log":
|
||||
pass
|
||||
elif arg["type"] == "normal":
|
||||
pass
|
||||
|
||||
entity.ffmpeg_arg = arg
|
||||
entity.ffmpeg_status = int(arg["status"])
|
||||
entity.ffmpeg_status_kor = str(arg["status"])
|
||||
entity.ffmpeg_percent = arg["data"]["percent"]
|
||||
entity.ffmpeg_arg["status"] = str(arg["status"])
|
||||
# self.P.logger.debug(arg)
|
||||
# import plugin
|
||||
# arg['status'] = str(arg['status'])
|
||||
# plugin.socketio_callback('status', arg)
|
||||
entity.refresh_status()
|
||||
|
||||
# FfmpegQueueEntity.static_index += 1
|
||||
# FfmpegQueueEntity.entity_list.append(self)
|
||||
|
||||
def add_queue(self, entity):
|
||||
try:
|
||||
# entity = QueueEntity.create(info)
|
||||
# if entity is not None:
|
||||
# LogicQueue.download_queue.put(entity)
|
||||
# return True
|
||||
entity.entity_id = self.static_index
|
||||
self.static_index += 1
|
||||
self.entity_list.append(entity)
|
||||
self.download_queue.put(entity)
|
||||
return True
|
||||
except Exception as exception:
|
||||
self.P.logger.error("Exception:%s", exception)
|
||||
self.P.logger.error(traceback.format_exc())
|
||||
return False
|
||||
|
||||
def set_max_ffmpeg_count(self, max_ffmpeg_count):
|
||||
self.max_ffmpeg_count = max_ffmpeg_count
|
||||
|
||||
def get_max_ffmpeg_count(self):
|
||||
return self.max_ffmpeg_count
|
||||
|
||||
def command(self, cmd, entity_id):
|
||||
self.P.logger.debug("command :%s %s", cmd, entity_id)
|
||||
ret = {}
|
||||
try:
|
||||
if cmd == "cancel":
|
||||
self.P.logger.debug("command :%s %s", cmd, entity_id)
|
||||
entity = self.get_entity_by_entity_id(entity_id)
|
||||
if entity is not None:
|
||||
if entity.ffmpeg_status == -1:
|
||||
entity.cancel = True
|
||||
entity.ffmpeg_status_kor = "취소"
|
||||
# entity.refresh_status()
|
||||
ret["ret"] = "refresh"
|
||||
elif entity.ffmpeg_status != 5:
|
||||
ret["ret"] = "notify"
|
||||
ret["log"] = "다운로드중 상태가 아닙니다."
|
||||
else:
|
||||
idx = entity.ffmpeg_arg["data"]["idx"]
|
||||
import ffmpeg
|
||||
|
||||
ffmpeg.Ffmpeg.stop_by_idx(idx)
|
||||
entity.refresh_status()
|
||||
ret["ret"] = "refresh"
|
||||
elif cmd == "reset":
|
||||
if self.download_queue is not None:
|
||||
with self.download_queue.mutex:
|
||||
self.download_queue.queue.clear()
|
||||
for _ in self.entity_list:
|
||||
if _.ffmpeg_status == 5:
|
||||
import ffmpeg
|
||||
|
||||
idx = _.ffmpeg_arg["data"]["idx"]
|
||||
ffmpeg.Ffmpeg.stop_by_idx(idx)
|
||||
self.entity_list = []
|
||||
ret["ret"] = "refresh"
|
||||
elif cmd == "delete_completed":
|
||||
new_list = []
|
||||
for _ in self.entity_list:
|
||||
if _.ffmpeg_status_kor in ["파일 있음", "취소", "사용자중지"]:
|
||||
continue
|
||||
if _.ffmpeg_status != 7:
|
||||
new_list.append(_)
|
||||
self.entity_list = new_list
|
||||
ret["ret"] = "refresh"
|
||||
elif cmd == "remove":
|
||||
new_list = []
|
||||
for _ in self.entity_list:
|
||||
if _.entity_id == entity_id:
|
||||
continue
|
||||
new_list.append(_)
|
||||
self.entity_list = new_list
|
||||
ret["ret"] = "refresh"
|
||||
return ret
|
||||
except Exception as exception:
|
||||
self.P.logger.error("Exception:%s", exception)
|
||||
self.P.logger.error(traceback.format_exc())
|
||||
|
||||
def get_entity_by_entity_id(self, entity_id):
|
||||
for _ in self.entity_list:
|
||||
if _.entity_id == entity_id:
|
||||
return _
|
||||
return None
|
||||
|
||||
def get_entity_list(self):
|
||||
ret = []
|
||||
for x in self.entity_list:
|
||||
tmp = x.as_dict()
|
||||
ret.append(tmp)
|
||||
return ret
|
||||
@@ -51,10 +51,11 @@ from framework.util import Util
|
||||
from framework.common.util import headers
|
||||
from plugin import (
|
||||
LogicModuleBase,
|
||||
FfmpegQueueEntity,
|
||||
FfmpegQueue,
|
||||
default_route_socketio,
|
||||
)
|
||||
|
||||
# 철자가 틀린 부분이 있어서 분리함
|
||||
from .lib.plugin import FfmpegQueue, FfmpegQueueEntity
|
||||
from tool_base import d
|
||||
|
||||
# 패키지
|
||||
@@ -1025,13 +1026,32 @@ class LogicAniLife(LogicModuleBase):
|
||||
)
|
||||
|
||||
def scheduler_function(self):
|
||||
logger.debug(f"anilife scheduler_function::=========================")
|
||||
logger.debug(f"anilife scheduler_function:: =========================")
|
||||
|
||||
content_code_list = P.ModelSetting.get_list("anilife_auto_code_list", "|")
|
||||
url = f'{P.ModelSetting.get("anilife_url")}/dailyani'
|
||||
|
||||
if "all" in content_code_list:
|
||||
url = f'{P.ModelSetting.get("anilife_url")}/dailyani'
|
||||
ret_data = LogicAniLife.get_auto_anime_info(self, url=url)
|
||||
|
||||
elif len(content_code_list) > 0:
|
||||
for item in content_code_list:
|
||||
url = P.ModelSetting.get("anilife_url") + "/detail/id/" + item
|
||||
print("scheduling url: %s", url)
|
||||
# ret_data = LogicOhli24.get_auto_anime_info(self, url=url)
|
||||
content_info = self.get_series_info(item)
|
||||
|
||||
logger.debug(content_info)
|
||||
# exit()
|
||||
|
||||
for episode_info in content_info["episode"]:
|
||||
add_ret = self.add(episode_info)
|
||||
if add_ret.startswith("enqueue"):
|
||||
self.socketio_callback("list_refresh", "")
|
||||
# logger.debug(f"data: {data}")
|
||||
# self.current_data = data
|
||||
# db에서 다운로드 완료 유무 체크
|
||||
|
||||
def plugin_load(self):
|
||||
self.queue = FfmpegQueue(
|
||||
P, P.ModelSetting.get_int("anilife_max_ffmpeg_process_count")
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
{{ macros.m_tab_content_start('auto', false) }}
|
||||
{{ macros.setting_global_scheduler_sub_button(arg['scheduler'], arg['is_running']) }}
|
||||
{{ macros.setting_input_text('anilife_interval', '스케쥴링 실행 정보', value=arg['anilife_interval'], col='3', desc=['Interval(minute 단위)이나 Cron 설정']) }}
|
||||
{{ macros.setting_input_text('anilife_interval', '스케쥴링 실행 정보', value=arg['anilife_interval'], col='4', desc=['Interval(minute 단위)이나 Cron 설정']) }}
|
||||
{{ macros.setting_checkbox('anilife_auto_start', '시작시 자동실행', value=arg['anilife_auto_start'], desc='On : 시작시 자동으로 스케쥴러에 등록 됩니다.') }}
|
||||
{{ macros.setting_input_textarea('anilife_auto_code_list', '자동 다운로드할 작품 코드', desc=['구분자 | 또는 엔터'], value=arg['anilife_auto_code_list'], row='10') }}
|
||||
{{ macros.setting_checkbox('anilife_auto_mode_all', '에피소드 모두 받기', value=arg['anilife_auto_mode_all'], desc=['On : 이전 에피소드를 모두 받습니다.', 'Off : 최신 에피소드만 받습니다.']) }}
|
||||
|
||||
Reference in New Issue
Block a user