diff --git a/data/db/menu.yaml b/data/db/menu.yaml new file mode 100644 index 0000000..a8ac393 --- /dev/null +++ b/data/db/menu.yaml @@ -0,0 +1,44 @@ +# 카테고리 +# uri 가 plugin인 경우 name 값은 대체 + +#- name: "토렌트" +# list: +# - uri: "rss" + + +#- name: "기본 기능" +# list: +# - uri: "terminal" +# - uri: "command" +# - uri: "flaskfilemanager" +# - uri: "flaskcode" +# - uri: "number_baseball" + + +#- name: "링크" +# list: +# - uri: "https://app.plex.tv" +# name: "Plex" +# target: "_self" +# - uri: "https://www.netflix.com" +# name: "Netflix" + + +- name: "시스템" + list: + - uri: "system" + name: "설정" + - uri: "setting" + name: "확장 설정" + - uri: "system/plugin" + name: "플러그인 관리" + - uri: "-" + - uri: "system/logout" + name: "로그아웃" + - uri: "system/restart" + name: "재시작(업데이트)" + - uri: "system/shutdown" + #uri: "javascript:shutdown_confirm();" + name: "종료" + + \ No newline at end of file diff --git a/data/db/system.db b/data/db/system.db new file mode 100644 index 0000000..c7cd2c5 Binary files /dev/null and b/data/db/system.db differ diff --git a/lib/framework/init_plugin.py b/lib/framework/init_plugin.py index 36a69ff..da24fc8 100644 --- a/lib/framework/init_plugin.py +++ b/lib/framework/init_plugin.py @@ -43,7 +43,7 @@ class PluginManager: for t in tmps: if not t.startswith('_') and os.path.isdir(os.path.join(plugin_path, t)): add_plugin_list.append(t) - cls.all_package_list[t] = {'pos':'normal', 'path':os.path.join(plugin_path, t)} + cls.all_package_list[t] = {'pos':'normal', 'path':os.path.join(plugin_path, t), 'loading':(F.config.get('plugin_loading_only_devpath', None) != True)} plugins = plugins + add_plugin_list except Exception as exception: @@ -64,7 +64,7 @@ class PluginManager: for t in tmps: if not t.startswith('_') and os.path.isdir(os.path.join(plugin_path, t)): add_plugin_list.append(t) - cls.all_package_list[t] = {'pos':'dev', 'path':os.path.join(plugin_path, t)} + cls.all_package_list[t] = {'pos':'dev', 'path':os.path.join(plugin_path, t), 'loading':True} plugins = plugins + add_plugin_list except Exception as exception: F.logger.error('Exception:%s', exception) diff --git a/lib/framework/init_route.py b/lib/framework/init_route.py index a68853e..7acbc18 100644 --- a/lib/framework/init_route.py +++ b/lib/framework/init_route.py @@ -34,10 +34,15 @@ def global_ajax(sub): elif sub == 'is_available_edit': # globalEditBtn try: - import flaskcode - from flaskcode.setup import P as PP - ret = {'ret':True, 'target':PP.ModelSetting.get('setting_open_target')} - return jsonify(ret) + if F.PluginManager.all_package_list['flaskcode']['loading']: + PP = F.PluginManager.all_package_list['flaskcode']['P'] + #import flaskcode + #from flaskcode.setup import P as PP + ret = {'ret':True, 'target':PP.ModelSetting.get('setting_open_target')} + return jsonify(ret) + else: + return jsonify({'ret':False}) + except: return jsonify({'ret':False}) elif sub == 'command_modal_hide': diff --git a/lib/framework/templates/base.html b/lib/framework/templates/base.html index 6eddcc3..f8e22dd 100644 --- a/lib/framework/templates/base.html +++ b/lib/framework/templates/base.html @@ -9,13 +9,6 @@ {% endblock %} - - - - diff --git a/lib/support/__init__.py b/lib/support/__init__.py index bea18d8..1746d13 100644 --- a/lib/support/__init__.py +++ b/lib/support/__init__.py @@ -15,7 +15,6 @@ logger = get_logger() from .base.aes import SupportAES from .base.discord import SupportDiscord from .base.file import SupportFile -from .base.process import SupportProcess from .base.string import SupportString from .base.subprocess import SupportSubprocess from .base.telegram import SupportTelegram diff --git a/lib/support/base/process.py b/lib/support/base/process.py deleted file mode 100644 index 5738a4e..0000000 --- a/lib/support/base/process.py +++ /dev/null @@ -1,48 +0,0 @@ -import os, sys, traceback, subprocess, json, platform -from . import logger - - -class SupportProcess(object): - - @classmethod - def execute(cls, command, format=None, shell=False, env=None, timeout=1000): - logger.debug(command) - try: - if platform.system() == 'Windows': - command = ' '.join(command) - - iter_arg = '' - process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=shell, env=env, encoding='utf8') - try: - process_ret = process.wait(timeout=timeout) # wait for the subprocess to exit - except: - import psutil - process = psutil.Process(process.pid) - for proc in process.children(recursive=True): - proc.kill() - process.kill() - return "timeout" - ret = [] - with process.stdout: - for line in iter(process.stdout.readline, iter_arg): - ret.append(line.strip()) - - if format is None: - ret2 = '\n'.join(ret) - elif format == 'json': - try: - index = 0 - for idx, tmp in enumerate(ret): - #logger.debug(tmp) - if tmp.startswith('{') or tmp.startswith('['): - index = idx - break - ret2 = json.loads(''.join(ret[index:])) - except: - ret2 = None - return ret2 - except Exception as e: - logger.error(f'Exception:{str(e)}', ) - logger.error(traceback.format_exc()) - logger.error('command : %s', command) - \ No newline at end of file diff --git a/lib/support/base/subprocess.py b/lib/support/base/subprocess.py index af40edb..ed351b7 100644 --- a/lib/support/base/subprocess.py +++ b/lib/support/base/subprocess.py @@ -132,13 +132,16 @@ class SupportSubprocess(object): self.start_send_callback() if self.process is not None: self.process.wait() - #logger.info(f"{self.command} 정상 종료") - if self.stdout_queue != None: - self.stdout_queue.put('') + logger.info(f"{self.command} 정상 종료") except Exception as e: logger.error(f'Exception:{str(e)}') logger.error(traceback.format_exc()) - + if self.stdout_callback != None: + self.stdout_callback('error', str(e)) + self.stdout_callback('error', str(traceback.format_exc())) + finally: + if self.stdout_callback != None: + self.stdout_callback('thread_end', None) def start_communicate(self): @@ -150,8 +153,6 @@ class SupportSubprocess(object): def rdr(): while True: - if self.process == None: - break buf = self.process.stdout.read(1) if buf: _queue.put( buf ) @@ -178,10 +179,9 @@ class SupportSubprocess(object): except: pass if r is not None: - if self.stdout_queue != None: - self.stdout_queue.put(r) - if self.stdout_queue != None: # 사용자 중지 - self.stdout_queue.put('') + #print(f"{r=}") + self.stdout_queue.put(r) + self.stdout_queue.put('') for tgt in [rdr, clct]: th = threading.Thread(target=tgt) th.setDaemon(True) @@ -200,10 +200,6 @@ class SupportSubprocess(object): else: if self.stdout_callback != None: self.stdout_callback('log', line) - self.send_to_ui_thread = None - self.stdout_queue = None - self.process = None - th = threading.Thread(target=func, args=()) th.setDaemon(True) th.start() @@ -222,7 +218,7 @@ class SupportSubprocess(object): logger.error(traceback.format_exc()) finally: try: - self.stdout_queue = None + #self.stdout_queue = None self.process.kill() except: pass diff --git a/lib/system/___logic.py b/lib/system/___logic.py deleted file mode 100644 index e27bdb2..0000000 --- a/lib/system/___logic.py +++ /dev/null @@ -1,275 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################### -# python -import os -import traceback -import logging -from datetime import datetime -import string -import random -import json - -# third-party -import requests -from flask import Blueprint, request, Response, send_file, render_template, redirect, jsonify -from flask_login import login_user, logout_user, current_user, login_required - - -from framework import F, frame, app, db, scheduler, VERSION, path_app_root, logger, Job, User -from framework.util import Util - -# 패키지 -from .model import ModelSetting -import system - -######################################################### - -class SystemLogic(object): - point = 0 - db_default = { - 'db_version' : '1', - 'port' : '9999', - 'ddns' : 'http://localhost:9999', - #'url_filebrowser' : 'http://localhost:9998', - #'url_celery_monitoring' : 'http://localhost:9997', - 'id' : 'admin', - 'pw' : '//nCv0/YkVI3U2AAgYwOuJ2hPlQ7cDYIbuaCt4YJupY=', - 'system_start_time' : '', - 'repeat' : '', - 'auto_restart_hour' : '12', - #'unique' : '', - 'theme' : 'Cerulean', - 'log_level' : '10', - 'use_login' : 'False', - 'link_json' : '[{"type":"link","title":"위키","url":"https://sjva.me/wiki/public/start"}]', - 'plugin_dev_path': '', - 'plugin_tving_level2' : 'False', - 'web_title' : 'Home', - 'my_ip' : '', - 'wavve_guid' : '', - - #인증 - 'auth_use_apikey' : 'False', - 'auth_apikey' : '', - #'hide_menu' : 'True', - - #Selenium - 'selenium_remote_url' : '', - 'selenium_remote_default_option' : '--no-sandbox\n--disable-gpu', - 'selenium_binary_default_option' : '', - - # notify - 'notify_telegram_use' : 'False', - 'notify_telegram_token' : '', - 'notify_telegram_chat_id' : '', - 'notify_telegram_disable_notification' : 'False', - 'notify_discord_use' : 'False', - 'notify_discord_webhook' : '', - - 'notify_advaned_use' : 'False', - 'notify_advaned_policy' : u"# 각 플러그인 설정 설명에 명시되어 있는 ID = 형식\n# DEFAULT 부터 주석(#) 제거 후 작성\n\n# DEFAULT = ", - - # telegram - 'telegram_bot_token' : '', - 'telegram_bot_auto_start' : 'False', - 'telegram_resend' : 'False', - 'telegram_resend_chat_id' : '', - - # 홈페이지 연동 2020-06-07 - 'sjva_me_user_id' : '', - 'auth_status' : '', - 'sjva_id' : '', - - # memo - 'memo' : '', - - # tool - decrypt - 'tool_crypt_use_user_key' : 'False', - 'tool_crypt_user_key' : '', - 'tool_crypt_encrypt_word' : '', - 'tool_crypt_decrypt_word' : '', - - 'use_beta' : 'False', - } - - - - @staticmethod - def get_info(): - info = {} - import platform - info['platform'] = platform.platform() - info['processor'] = platform.processor() - - import sys - info['python_version'] = sys.version - info['version'] = VERSION - info['recent_version'] = SystemLogic.recent_version - info['path_app_root'] = path_app_root - info['running_type'] = u'%s. 비동기 작업 : %s' % (frame.config['running_type'], u"사용" if frame.config['use_celery'] else "미사용") - import system - - info['auth'] = frame.config['member']['auth_desc'] - info['cpu_percent'] = 'not supported' - info['memory'] = 'not supported' - info['disk'] = 'not supported' - if frame.config['running_type'] != 'termux': - try: - import psutil - from framework.util import Util - info['cpu_percent'] = '%s %%' % psutil.cpu_percent() - tmp = psutil.virtual_memory() - #info['memory'] = [Util.sizeof_fmt(tmp[0], suffix='B'), Util.sizeof_fmt(tmp[3]), Util.sizeof_fmt(tmp[1]), tmp[2]] - info['memory'] = u'전체 : %s 사용량 : %s 남은량 : %s (%s%%)' % (Util.sizeof_fmt(tmp[0], suffix='B'), Util.sizeof_fmt(tmp[3], suffix='B'), Util.sizeof_fmt(tmp[1], suffix='B'), tmp[2]) - except: - pass - - try: - import platform - if platform.system() == 'Windows': - s = os.path.splitdrive(path_app_root) - root = s[0] - else: - root = '/' - tmp = psutil.disk_usage(root) - info['disk'] = u'전체 : %s 사용량 : %s 남은량 : %s (%s%%) - 드라이브 (%s)' % (Util.sizeof_fmt(tmp[0], suffix='B'), Util.sizeof_fmt(tmp[1], suffix='B'), Util.sizeof_fmt(tmp[2], suffix='B'), tmp[3], root) - except Exception as exception: - pass - try: - tmp = SystemLogic.get_setting_value('system_start_time') - #logger.debug('SYSTEM_START_TIME:%s', tmp) - tmp_datetime = datetime.strptime(tmp, '%Y-%m-%d %H:%M:%S') - timedelta = datetime.now() - tmp_datetime - info['time'] = u'시작 : %s 경과 : %s 재시작 : %s' % (tmp, str(timedelta).split('.')[0], frame.config['arg_repeat']) - except Exception as exception: - info['time'] = str(exception) - return info - - - @staticmethod - def setting_save_system(req): - try: - for key, value in req.form.items(): - logger.debug('Key:%s Value:%s', key, value) - entity = db.session.query(ModelSetting).filter_by(key=key).with_for_update().first() - entity.value = value - #if key == 'theme': - # SystemLogic.change_theme(value) - db.session.commit() - lists = ModelSetting.query.all() - SystemLogic.setting_list = Util.db_list_to_dict(lists) - frame.users[db.session.query(ModelSetting).filter_by(key='id').first().value] = User(db.session.query(ModelSetting).filter_by(key='id').first().value, passwd_hash=db.session.query(ModelSetting).filter_by(key='pw').first().value) - SystemLogic.set_restart_scheduler() - frame.set_level(int(db.session.query(ModelSetting).filter_by(key='log_level').first().value)) - - return True - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return False - - @staticmethod - def setting_save_after(): - try: - frame.users[ModelSetting.get('id')] = User(ModelSetting.get('id'), passwd_hash=ModelSetting.get('pw')) - SystemLogic.set_restart_scheduler() - frame.set_level(int(db.session.query(ModelSetting).filter_by(key='log_level').first().value)) - from .logic_site import SystemLogicSite - SystemLogicSite.get_daum_cookies(force=True) - SystemLogicSite.create_tving_instance() - return True - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return False - - @staticmethod - def change_theme(theme): - try: - source = os.path.join(path_app_root, 'static', 'css', 'theme', '%s_bootstrap.min.css' % theme) - target = os.path.join(path_app_root, 'static', 'css', 'bootstrap.min.css') - os.remove(target) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return False - - @staticmethod - def get_setting_value(key): - try: - #logger.debug('get_setting_value:%s', key) - entity = db.session.query(ModelSetting).filter_by(key=key).first() - if entity is None: - return None - else: - return entity.value - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - logger.error('error key : %s', key) - return False - - - - - - - - @staticmethod - def command_run(command_text): - try: - ret = {} - tmp = command_text.strip().split(' ') - if not tmp: - ret['ret'] = 'success' - ret['log'] = 'Empty..' - return ret - if tmp[0] == 'set': - if len(tmp) == 3: - if tmp[1] == 'token': - tmp[1] = 'unique' - entity = db.session.query(ModelSetting).filter_by(key=tmp[1]).with_for_update().first() - if entity is None: - ret['ret'] = 'fail' - ret['log'] = '%s not exist' % tmp[1] - return ret - entity.value = tmp[2] if tmp[2] != 'EMPTY' else "" - db.session.commit() - ret['ret'] = 'success' - ret['log'] = '%s - %s' % (tmp[1], tmp[2]) - return ret - - if tmp[0] == 'set2': - if tmp[1] == 'klive': - from klive import ModelSetting as KLiveModelSetting - if KLiveModelSetting.get(tmp[2]) is not None: - KLiveModelSetting.set(tmp[2], tmp[3]) - ret['ret'] = 'success' - ret['log'] = f'KLive 설정 값 변경 : {tmp[2]} - {tmp[3]}' - return ret - - - ret['ret'] = 'fail' - ret['log'] = 'wrong command' - return ret - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - ret['ret'] = 'fail' - ret['log'] = str(exception) - return ret - - @staticmethod - def link_save(link_data_str): - try: - data = json.loads(link_data_str) - entity = db.session.query(ModelSetting).filter_by(key='link_json').with_for_update().first() - entity.value = link_data_str - db.session.commit() - SystemLogic.apply_menu_link() - return True - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return False - diff --git a/lib/system/__init__.py b/lib/system/__init__.py index 82c2912..e69de29 100644 --- a/lib/system/__init__.py +++ b/lib/system/__init__.py @@ -1,14 +0,0 @@ -""" -from .plugin import blueprint, menu, plugin_load, plugin_unload, restart, shutdown -from .logic import SystemLogic -from .model import ModelSetting -from .model import ModelSetting as SystemModelSetting - - -from .logic_plugin import LogicPlugin -from .logic_selenium import SystemLogicSelenium -from .logic_command import SystemLogicCommand - -from .logic_site import SystemLogicSite - -""" \ No newline at end of file diff --git a/lib/system/logic_auth.py b/lib/system/logic_auth.py deleted file mode 100644 index 3411b0a..0000000 --- a/lib/system/logic_auth.py +++ /dev/null @@ -1,162 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################### -# python -import codecs -import json -import os -import random -import string -import traceback - -# third-party -import requests -from flask import (Blueprint, Response, jsonify, redirect, render_template, - request, send_file) -from framework import app, frame, path_app_root -from framework.util import Util - -from .model import ModelSetting -# 패키지 -from .plugin import logger, package_name - -# sjva 공용 - - - -class SystemLogicAuth(object): - @staticmethod - def process_ajax(sub, req): - logger.debug(sub) - try: - if sub == 'apikey_generate': - ret = SystemLogicAuth.apikey_generate() - return jsonify(ret) - elif sub == 'do_auth': - ret = SystemLogicAuth.do_auth() - return jsonify(ret) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - ########################################################################## - - - - @staticmethod - def get_auth_status(retry=True): - try: - value = ModelSetting.get('auth_status') - ret = {'ret' : False, 'desc' : '', 'level' : 0, 'point': 0} - if value == '': - ret['desc'] = '미인증' - elif value == 'wrong_id': - ret['desc'] = '미인증 - 홈페이지 아이디가 없습니다.' - elif value == 'too_many_sjva': - ret['desc'] = '미인증 - 너무 많은 SJVA를 사용중입니다.' - elif value == 'wrong_apikey': - ret['desc'] = '미인증 - 홈페이지에 등록된 APIKEY와 다릅니다.' - elif value == 'auth_status': - ret['desc'] = '인증 실패' - else: - status = SystemLogicAuth.check_auth_status(value) - if status is not None and status['ret']: - ret['ret'] = status['ret'] - ret['desc'] = '인증되었습니다. (회원등급:%s, 포인트:%s)' % (status['level'], status['point']) - ret['level'] = status['level'] - ret['point'] = status['point'] - else: - if retry: - SystemLogicAuth.do_auth() - #ModelSetting.set('auth_status', SystemLogicAuth.make_auth_status()) - return SystemLogicAuth.get_auth_status(retry=False) - else: - ret['desc'] = '잘못된 값입니다. 다시 인증하세요.' - return ret - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - @staticmethod - def check_auth_status(value=None): - try: - from support import SupportAES - mykey=(codecs.encode(SystemLogicAuth.get_ip().encode(), 'hex').decode() + codecs.encode(ModelSetting.get('auth_apikey').encode(), 'hex').decode()).zfill(32)[:32].encode() - logger.debug(mykey) - tmp = SupportAES.decrypt(value, mykey=mykey) - tmp = tmp.split('_') - ret = {} - ret['ret'] = (ModelSetting.get('sjva_id') == tmp[0]) - ret['level'] = int(tmp[1]) - ret['point'] = int(tmp[2]) - return ret - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - @staticmethod - def make_auth_status(level, point): - try: - from support.base import SupportAES - mykey=(codecs.encode(SystemLogicAuth.get_ip().encode(), 'hex').decode() + codecs.encode(ModelSetting.get('auth_apikey').encode(), 'hex').decode()).zfill(32)[:32].encode() - ret = SupportAES.encrypt(str('%s_%s_%s' % (ModelSetting.get('sjva_id'), level, point)), mykey=mykey) - logger.debug(ret) - return ret - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - @staticmethod - def get_ip(): - import socket - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - # doesn't even have to be reachable - s.connect(('10.255.255.255', 1)) - IP = s.getsockname()[0] - except Exception: - IP = '127.0.0.1' - finally: - s.close() - logger.debug('IP:%s', IP) - return IP - - @staticmethod - def do_auth(): - try: - ret = {'ret':False, 'msg':'', 'level':0, 'point':0} - apikey = ModelSetting.get('auth_apikey') - user_id = ModelSetting.get('sjva_me_user_id') - if len(apikey) != 10: - ret['msg'] = 'APIKEY 문자 길이는 10자리여야합니다.' - return ret - if user_id == '': - ret['msg'] = '홈페이지 ID가 없습니다.' - return ret - - data = requests.post(f"{frame.config['DEFINE']['WEB_DIRECT_URL']}/sjva/auth.php", data={'apikey':apikey,'user_id':user_id, 'sjva_id':ModelSetting.get('sjva_id')}).json() - if data['result'] == 'success': - ret['ret'] = True - ret['msg'] = u'총 %s개 등록
회원등급:%s, 포인트:%s' % (data['count'], data['level'], data['point']) - ret['level'] = int(data['level']) - ret['point'] = int(data['point']) - ModelSetting.set('auth_status', SystemLogicAuth.make_auth_status(ret['level'], ret['point'])) - else: - ModelSetting.set('auth_status', data['result']) - tmp = SystemLogicAuth.get_auth_status(retry=False) - ret['ret'] = tmp['ret'] - ret['msg'] = tmp['desc'] - return ret - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - ret['msg'] = '인증 실패' - ret['level'] = -1 - ret['point'] = -1 - ModelSetting.set('auth_status', 'auth_fail') - - return ret - - - diff --git a/lib/system/logic_command.py b/lib/system/logic_command.py deleted file mode 100644 index 97c5338..0000000 --- a/lib/system/logic_command.py +++ /dev/null @@ -1,246 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################### -# python -import os -import traceback -import logging -import platform -import subprocess -import threading -import sys -import io -import time -import json -import queue -# third-party - -# sjva 공용 - -from framework import path_app_root, socketio, app, logger - -# 패키지 - - - -class SystemLogicCommand(object): - - commands = None - process = None - stdout_queue = None - thread = None - send_to_ui_thread = None - return_log = None - @staticmethod - def start(title, commands, clear=True, wait=False, show_modal=True): - try: - if show_modal: - if clear: - socketio.emit("command_modal_clear", None, namespace='/framework', broadcast=True) - SystemLogicCommand.return_log = [] - SystemLogicCommand.title = title - SystemLogicCommand.commands = commands - SystemLogicCommand.thread = threading.Thread(target=SystemLogicCommand.execute_thread_function, args=(show_modal,)) - SystemLogicCommand.thread.setDaemon(True) - SystemLogicCommand.thread.start() - if wait: - time.sleep(1) - SystemLogicCommand.thread.join() - return SystemLogicCommand.return_log - - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - @staticmethod - def execute_thread_function(show_modal): - try: - #if wait: - if show_modal: - socketio.emit("loading_hide", None, namespace='/framework', broadcast=True) - for command in SystemLogicCommand.commands: - #logger.debug('Command :%s', command) - if command[0] == 'msg': - if show_modal: - socketio.emit("command_modal_add_text", '%s\n\n' % command[1], namespace='/framework', broadcast=True) - elif command[0] == 'system': - if show_modal: - socketio.emit("command_modal_add_text", '$ %s\n\n' % command[1], namespace='/framework', broadcast=True) - os.system(command[1]) - else: - show_command = True - if command[0] == 'hide': - show_command = False - command = command[1:] - #SystemLogicCommand.process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, bufsize=1) - SystemLogicCommand.process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, encoding='utf8') - SystemLogicCommand.start_communicate(command, show_command=show_command) - SystemLogicCommand.send_queue_start(show_modal) - if SystemLogicCommand.process is not None: - SystemLogicCommand.process.wait() - time.sleep(1) - - except Exception as exception: - #logger.error('Exception:%s', exception) - #logger.error(traceback.format_exc()) - if show_modal: - socketio.emit("command_modal_show", SystemLogicCommand.title, namespace='/framework', broadcast=True) - socketio.emit("command_modal_add_text", str(exception), namespace='/framework', broadcast=True) - socketio.emit("command_modal_add_text", str(traceback.format_exc()), namespace='/framework', broadcast=True) - - - - @staticmethod - def start_communicate(current_command, show_command=True): - SystemLogicCommand.stdout_queue = queue.Queue() - if show_command: - SystemLogicCommand.stdout_queue.put('$ %s\n' % ' '.join(current_command)) - sout = io.open(SystemLogicCommand.process.stdout.fileno(), 'rb', closefd=False) - #serr = io.open(process.stderr.fileno(), 'rb', closefd=False) - - def Pump(stream): - queue = queue.Queue() - - def rdr(): - logger.debug('START RDR') - while True: - buf = SystemLogicCommand.process.stdout.read(1) - if buf: - queue.put( buf ) - else: - queue.put( None ) - break - logger.debug('END RDR') - queue.put( None ) - time.sleep(1) - - #Logic.command_close() - def clct(): - active = True - logger.debug('START clct') - while active: - r = queue.get() - if r is None: - break - try: - while True: - r1 = queue.get(timeout=0.005) - if r1 is None: - active = False - break - else: - r += r1 - except: - pass - if r is not None: - try: - r = r.decode('utf-8') - except Exception as exception: - #logger.error('Exception:%s', e) - #logger.error(traceback.format_exc()) - try: - r = r.decode('cp949') - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - try: - r = r.decode('euc-kr') - except: - pass - - SystemLogicCommand.stdout_queue.put(r) - #SystemLogicCommand.return_log.append(r) - SystemLogicCommand.return_log += r.split('\n') - logger.debug('IN:%s', r) - SystemLogicCommand.stdout_queue.put('') - logger.debug('END clct') - #Logic.command_close() - for tgt in [rdr, clct]: - th = threading.Thread(target=tgt) - th.setDaemon(True) - th.start() - Pump(sout) - #Pump(serr, 'stderr') - - @staticmethod - def send_queue_start(show_modal): - def send_to_ui_thread_function(): - logger.debug('send_queue_thread_function START') - if show_modal: - socketio.emit("command_modal_show", SystemLogicCommand.title, namespace='/framework', broadcast=True) - while SystemLogicCommand.stdout_queue: - line = SystemLogicCommand.stdout_queue.get() - logger.debug('Send to UI :%s', line) - if line == '': - if show_modal: - socketio.emit("command_modal_add_text", "\n", namespace='/framework', broadcast=True) - break - else: - if show_modal: - socketio.emit("command_modal_add_text", line, namespace='/framework', broadcast=True) - SystemLogicCommand.send_to_ui_thread = None - SystemLogicCommand.stdout_queue = None - SystemLogicCommand.process = None - logger.debug('send_to_ui_thread_function END') - - if SystemLogicCommand.send_to_ui_thread is None: - SystemLogicCommand.send_to_ui_thread = threading.Thread(target=send_to_ui_thread_function, args=()) - SystemLogicCommand.send_to_ui_thread.start() - - @staticmethod - def plugin_unload(): - try: - if SystemLogicCommand.process is not None and SystemLogicCommand.process.poll() is None: - import psutil - process = psutil.Process(SystemLogicCommand.process.pid) - for proc in SystemLogicCommand.process.children(recursive=True): - proc.kill() - SystemLogicCommand.process.kill() - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - ################################## - # 외부 호출 - @staticmethod - def execute_command_return(command, format=None, force_log=False): - from tool_base import ToolSubprocess - return ToolSubprocess.execute_command_return(command, format=format, force_log=force_log) - """ - try: - logger.debug('execute_command_return : %s', ' '.join(command)) - - if app.config['config']['running_type'] == 'windows': - command = ' '.join(command) - - process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, encoding='utf8') - ret = [] - with process.stdout: - for line in iter(process.stdout.readline, ''): - ret.append(line.strip()) - if force_log: - logger.debug(ret[-1]) - process.wait() # wait for the subprocess to exit - - - if format is None: - ret2 = '\n'.join(ret) - elif format == 'json': - try: - index = 0 - for idx, tmp in enumerate(ret): - #logger.debug(tmp) - if tmp.startswith('{') or tmp.startswith('['): - index = idx - break - ret2 = json.loads(''.join(ret[index:])) - except: - ret2 = None - - return ret2 - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - logger.error('command : %s', command) - """ - \ No newline at end of file diff --git a/lib/system/logic_command2.py b/lib/system/logic_command2.py deleted file mode 100644 index e8033b3..0000000 --- a/lib/system/logic_command2.py +++ /dev/null @@ -1,209 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################### -# python -import os -import traceback -import logging -import platform -import subprocess -import threading -import sys -import io -import time -import json -import queue -# third-party - -# sjva 공용 - -from framework import path_app_root, socketio, logger, app - -# 패키지 - -# 로그 -package_name = __name__.split('.')[0] -#logger = get_logger(package_name) -######################################################### - -class SystemLogicCommand2(object): - instance_list = [] - - def __init__(self, title, commands, clear=True, wait=False, show_modal=True): - self.title = title - self.commands = commands - self.clear = clear - self.wait = wait - self.show_modal = show_modal - - self.process = None - self.stdout_queue = None - self.thread = None - self.send_to_ui_thread = None - self.return_log = [] - SystemLogicCommand2.instance_list.append(self) - - - def start(self): - try: - if self.show_modal: - if self.clear: - socketio.emit("command_modal_clear", None, namespace='/framework', broadcast=True) - - self.thread = threading.Thread(target=self.execute_thread_function, args=()) - self.thread.setDaemon(True) - self.thread.start() - if self.wait: - time.sleep(1) - self.thread.join() - return self.return_log - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - def execute_thread_function(self): - try: - #if wait: - if self.show_modal: - socketio.emit("command_modal_show", self.title, namespace='/framework', broadcast=True) - socketio.emit("loading_hide", None, namespace='/framework', broadcast=True) - - for command in self.commands: - if command[0] == 'msg': - if self.show_modal: - socketio.emit("command_modal_add_text", '%s\n\n' % command[1], namespace='/framework', broadcast=True) - elif command[0] == 'system': - if self.show_modal: - socketio.emit("command_modal_add_text", '$ %s\n\n' % command[1], namespace='/framework', broadcast=True) - os.system(command[1]) - else: - show_command = True - if command[0] == 'hide': - show_command = False - command = command[1:] - #self.process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, bufsize=1) - self.process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, encoding='utf8') - self.start_communicate(command, show_command=show_command) - self.send_queue_start() - if self.process is not None: - self.process.wait() - time.sleep(1) - except Exception as exception: - if self.show_modal: - socketio.emit("command_modal_show", self.title, namespace='/framework', broadcast=True) - socketio.emit("command_modal_add_text", str(exception), namespace='/framework', broadcast=True) - socketio.emit("command_modal_add_text", str(traceback.format_exc()), namespace='/framework', broadcast=True) - - - def start_communicate(self, current_command, show_command=True): - self.stdout_queue = queue.Queue() - if show_command: - self.stdout_queue.put('$ %s\n' % ' '.join(current_command)) - sout = io.open(self.process.stdout.fileno(), 'rb', closefd=False) - #serr = io.open(process.stderr.fileno(), 'rb', closefd=False) - - def Pump(stream): - queue = queue.Queue() - - def rdr(): - #logger.debug('START RDR') - while True: - buf = self.process.stdout.read(1) - if buf: - queue.put( buf ) - else: - queue.put( None ) - break - #logger.debug('END RDR') - queue.put( None ) - time.sleep(1) - - #Logic.command_close() - def clct(): - active = True - #logger.debug('START clct') - while active: - r = queue.get() - if r is None: - break - try: - while True: - r1 = queue.get(timeout=0.005) - if r1 is None: - active = False - break - else: - r += r1 - except: - pass - if r is not None: - if app.config['config']['is_py2']: - try: - r = r.decode('utf-8') - except Exception as exception: - #logger.error('Exception:%s', e) - #logger.error(traceback.format_exc()) - try: - r = r.decode('cp949') - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - try: - r = r.decode('euc-kr') - except: - pass - - self.stdout_queue.put(r) - self.return_log += r.split('\n') - #logger.debug('IN:%s', r) - self.stdout_queue.put('') - #logger.debug('END clct') - #Logic.command_close() - for tgt in [rdr, clct]: - th = threading.Thread(target=tgt) - th.setDaemon(True) - th.start() - Pump(sout) - #Pump(serr, 'stderr') - - def send_queue_start(self): - def send_to_ui_thread_function(): - #logger.debug('send_queue_thread_function START') - if self.show_modal: - socketio.emit("command_modal_show", self.title, namespace='/framework', broadcast=True) - while self.stdout_queue: - line = self.stdout_queue.get() - #logger.debug('Send to UI :%s', line) - if line == '': - if self.show_modal: - socketio.emit("command_modal_add_text", "\n", namespace='/framework', broadcast=True) - break - else: - if self.show_modal: - socketio.emit("command_modal_add_text", line, namespace='/framework', broadcast=True) - self.send_to_ui_thread = None - self.stdout_queue = None - self.process = None - #logger.debug('send_to_ui_thread_function END') - - if self.send_to_ui_thread is None: - self.send_to_ui_thread = threading.Thread(target=send_to_ui_thread_function, args=()) - self.send_to_ui_thread.start() - - - @classmethod - def plugin_unload(cls): - for instance in cls.instance_list: - try: - if instance.process is not None and instance.process.poll() is None: - import psutil - process = psutil.Process(instance.process.pid) - for proc in instance.process.children(recursive=True): - proc.kill() - instance.process.kill() - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - finally: - try: instance.process.kill() - except: pass \ No newline at end of file diff --git a/lib/system/logic_env.py b/lib/system/logic_env.py deleted file mode 100644 index 16877a6..0000000 --- a/lib/system/logic_env.py +++ /dev/null @@ -1,130 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################### -# python -import logging -import os -import platform -import threading -import time -import traceback - -# third-party -from flask import (Blueprint, Response, jsonify, redirect, render_template, - request, send_file) -from framework import F, app, celery, path_app_root, path_data - -from .model import ModelSetting -# 패키지 -from .plugin import logger, package_name - -# sjva 공용 - - - -class SystemLogicEnv(object): - @staticmethod - def load_export(): - try: - from support import SupportFile - f = os.path.join(path_app_root, 'export.sh') - if os.path.exists(f): - return SupportFile.read_file(f) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - @staticmethod - def process_ajax(sub, req): - ret = False - try: - if sub == 'setting_save': - data = req.form['export'] - #logger.debug(data) - data = data.replace("\r\n", "\n" ).replace( "\r", "\n" ) - ret = False - if platform.system() != 'Windows': - f = os.path.join(path_app_root, 'export.sh') - with open(f, 'w') as f: - f.write(data) - #os.system("dos2unix export.sh") - ret = True - elif sub == 'ps': - def func(): - import system - commands = [ - ['msg', u'잠시만 기다려주세요.'], - ['ps', '-ef'], - ['top', '-n1'] - ] - #commands.append(['msg', u'설치가 완료되었습니다.']) - system.SystemLogicCommand.start('ps', commands) - t = threading.Thread(target=func, args=()) - t.setDaemon(True) - t.start() - elif sub == 'celery_test': - ret = SystemLogicEnv.celery_test() - elif sub == 'worker_start': - os.system('sh worker_start.sh &') - """ - def func(): - import system - commands = [ - ['msg', u'잠시만 기다려주세요.'], - ['sh', 'worker_start.sh'], - ] - #commands.append(['msg', u'설치가 완료되었습니다.']) - system.SystemLogicCommand.start('ps', commands) - t = threading.Thread(target=func, args=()) - t.setDaemon(True) - t.start() - """ - ret = True - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return jsonify(ret) - - - - @staticmethod - def celery_test(): - if F.config['use_celery']: - from celery import Celery - from celery.exceptions import NotRegistered, TimeoutError - - data = {} - try: - result = SystemLogicEnv.celery_test2.apply_async() - logger.debug(result) - try: - tmp = result.get(timeout=5, propagate=True) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - #result = SystemLogicEnv.celery_test2.delay() - data['ret'] = 'success' - data['data'] = tmp - except TimeoutError: - data['ret'] = 'timeout' - data['data'] = u'celery가 동작중이 아니거나 모든 프로세스가 작업중입니다.' - except NotRegistered: - data['ret'] = 'not_registered' - data['data'] = u'Not Registered' - #logger.debug(data) - else: - data['ret'] = 'no_celery' - data['data'] = u'celery 실행환경이 아닙니다.' - return data - - @staticmethod - @celery.task - def celery_test2(): - try: - logger.debug('!!!! celery_test2222') - import time - time.sleep(1) - data = u'정상입니다. 이 메시지는 celery 에서 반환됩니다. ' - return data - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) diff --git a/lib/system/logic_notify.py b/lib/system/logic_notify.py deleted file mode 100644 index 23727a0..0000000 --- a/lib/system/logic_notify.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################### -# python -import os -import traceback -import logging -import platform -import time - -# third-party -from flask import Blueprint, request, Response, send_file, render_template, redirect, jsonify - - -# sjva 공용 - -from framework import path_app_root, path_data -from tool_base import ToolBaseNotify -# 패키지 -from .plugin import logger, package_name -from .model import ModelSetting - - -class SystemLogicNotify(object): - @staticmethod - def process_ajax(sub, req): - try: - if sub == 'telegram_test': - ret = ToolBaseNotify.send_telegram_message(req.form['text'], bot_token=req.form['bot_token'], chat_id=req.form['chat_id']) - return jsonify(ret) - elif sub == 'discord_test': - ret = ToolBaseNotify.send_discord_message(req.form['text'], webhook_url=req.form['url']) - return jsonify(ret) - elif sub == 'advanced_test': - ret = ToolBaseNotify.send_advanced_message(req.form['text'], policy=req.form['policy'], message_id=req.form['message_id']) - return jsonify(ret) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return jsonify('exception') - diff --git a/lib/system/logic_plugin.py b/lib/system/logic_plugin.py deleted file mode 100644 index d0f1231..0000000 --- a/lib/system/logic_plugin.py +++ /dev/null @@ -1,290 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################### -# python -import json -import logging -import os -import platform -import time -import traceback -import zipfile - -# third-party -import requests -# sjva 공용 -from framework import app, frame, logger, path_data -from framework.util import Util -from support import SupportProcess - -import system - -# 패키지 -from .model import ModelSetting - - -class LogicPlugin(object): - plugin_loading = False - - - - current_loading_plugin_list = {} - - """ - custom_plugin_list = [] - @staticmethod - def loading(): - try: - custom_path = os.path.join(path_data, 'custom') - plugin_list = os.listdir(custom_path) - logger.debug(plugin_list) - for name in plugin_list: - try: - p = {} - p['name'] = name - p['plugin_name'] = name - mod = __import__('%s' % (p['plugin_name']), fromlist=[]) - p['local_info'] = getattr(mod, 'plugin_info') - p['status'] = 'latest' - LogicPlugin.custom_plugin_list.append(p) - except Exception as exception: - logger.error('NO Exception:%s', exception) - logger.debug('plunin not import : %s', p['plugin_name']) - p['local_info'] = None - p['status'] = 'no' - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - """ - - @staticmethod - def get_plugin_list(): - return LogicPlugin.current_loading_plugin_list - """ - try: - if not LogicPlugin.plugin_loading: - LogicPlugin.loading() - LogicPlugin.plugin_loading = True - return LogicPlugin.custom_plugin_list - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - """ - - - @staticmethod - def get_plugin_info(plugin_name): - try: - lists = LogicPlugin.get_plugin_list() - for key, value in lists.items(): - if key == plugin_name: - return value['info'] - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - """ - @staticmethod - def plugin_install(plugin_name): - logger.debug('plugin_name : %s', plugin_name) - try: - plugin_info = LogicPlugin.get_plugin_info(plugin_name) - - custom_path = os.path.join(path_data, 'custom') - - if 'platform' in plugin_info: - if platform.system() not in plugin_info['platform']: - return 'not_support_os' - if 'running_type' in plugin_info: - if app.config['config']['running_type'] not in plugin_info['running_type']: - return 'not_support_running_type' - git_clone_flag = True - if git_clone_flag: - # git clone - command = ['git', '-C', custom_path, 'clone', plugin_info['git'], '--depth', '1'] - ret = Util.execute_command(command) - return 'success' - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - """ - - @staticmethod - def plugin_uninstall(plugin_name): - logger.debug('plugin_name : %s', plugin_name) - try: - mod = __import__('%s' % (plugin_name), fromlist=[]) - mod_plugin_unload = getattr(mod, 'plugin_unload') - mod_plugin_unload() - time.sleep(1) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - try: - custom_path = os.path.join(path_data, 'custom') - plugin_path = os.path.join(custom_path, plugin_name) - if os.path.exists(plugin_path): - try: - import framework.common.celery as celery_task - celery_task.rmtree(plugin_path) - except Exception as exception: - try: - logger.debug('plugin_uninstall') - os.system('rmdir /S /Q "%s"' % plugin_path) - except: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - if os.path.exists(plugin_path): - return 'fail' - else: - return 'success' - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - @staticmethod - def custom_plugin_update(): - try: - if os.environ.get('UPDATE_STOP') == 'true': - return - if os.environ.get('PLUGIN_UPDATE_FROM_PYTHON') == 'false': - return - if frame.config['debug'] == True: - return - if frame.config.get('plugin_update', True) != True: - return - - custom_path = os.path.join(path_data, 'plugins') - tmps = os.listdir(custom_path) - for t in tmps: - plugin_path = os.path.join(custom_path, t) - try: - if t == 'torrent_info': - os.remove(os.path.join(plugin_path, 'info.json')) - except: - pass - if t.startswith('_'): - continue - if os.path.exists(os.path.join(plugin_path, '.git')): - command = ['git', '-C', plugin_path, 'reset', '--hard', 'HEAD'] - ret = SupportProcess.execute(command) - command = ['git', '-C', plugin_path, 'pull'] - ret = SupportProcess.execute(command) - logger.debug("%s\n%s", plugin_path, ret) - else: - logger.debug(f"plugin_path is not git repo") - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - @staticmethod - def plugin_install_by_api(plugin_git, zip_url, zip_filename): - logger.debug('plugin_git : %s', plugin_git) - logger.debug('zip_url : %s', zip_url) - logger.debug('zip_filename : %s', zip_filename) - - is_git = True if plugin_git != None and plugin_git != '' else False - ret = {} - try: - if is_git: - name = plugin_git.split('/')[-1] - else: - name = zip_filename.split('.')[0] - - custom_path = os.path.join(path_data, 'custom') - plugin_path = os.path.join(custom_path, name) - logger.debug(plugin_path) - plugin_info = None - if os.path.exists(plugin_path): - ret['ret'] = 'already_exist' - ret['log'] = '이미 설치되어 있습니다.' - else: - if plugin_git and plugin_git.startswith('http'): - for tag in ['main', 'master']: - try: - info_url = plugin_git.replace('github.com', 'raw.githubusercontent.com') + '/%s/info.json' % tag - plugin_info = requests.get(info_url).json() - if plugin_info is not None: - break - except: - pass - if zip_filename and zip_filename != '': - import zipfile - - from tool_base import ToolBaseFile - zip_filepath = os.path.join(path_data, 'tmp', zip_filename) - extract_filepath = os.path.join(path_data, 'tmp', name) - logger.error(zip_url) - logger.warning(zip_filepath) - if ToolBaseFile.download(zip_url, zip_filepath): - #logger.warning(os.path.exists(zip_filepath)) - with zipfile.ZipFile(zip_filepath, 'r') as zip_ref: - zip_ref.extractall(extract_filepath) - plugin_info_filepath = os.path.join(extract_filepath, 'info.json') - if os.path.exists(plugin_info_filepath): - plugin_info = ToolBaseFile.read_json(plugin_info_filepath) - if plugin_info == None: - plugin_info = {} - flag = True - if 'platform' in plugin_info: - if platform.system() not in plugin_info['platform']: - ret['ret'] = 'not_support_os' - ret['log'] = '설치 가능한 OS가 아닙니다.' - flag = False - if flag and 'running_type' in plugin_info: - if app.config['config']['running_type'] not in plugin_info['running_type']: - ret['ret'] = 'not_support_running_type' - ret['log'] = '설치 가능한 실행타입이 아닙니다.' - flag = False - if flag and 'policy_level' in plugin_info: - if plugin_info['policy_level'] > app.config['config']['level']: - ret['ret'] = 'policy_level' - ret['log'] = '설치 가능 회원등급보다 낮습니다.' - flag = False - if flag and 'policy_point' in plugin_info: - if plugin_info['policy_level'] > app.config['config']['point']: - ret['ret'] = 'policy_level' - ret['log'] = '설치 가능 포인트보다 낮습니다.' - flag = False - - if flag: - if plugin_git and plugin_git.startswith('http'): - command = ['git', '-C', custom_path, 'clone', plugin_git + '.git', '--depth', '1'] - log = Util.execute_command(command) - if zip_filename and zip_filename != '': - import shutil - if os.path.exists(plugin_path) == False: - shutil.move(extract_filepath, plugin_path) - else: - for tmp in os.listdir(extract_filepath): - shutil.move(os.path.join(extract_filepath, tmp), plugin_path) - log = '' - logger.debug(plugin_info) - # 2021-12-31 - if 'dependency' in plugin_info: - for dep in plugin_info['dependency']: - for key, value in LogicPlugin.get_plugin_list().items(): - if key == dep['name']: - logger.debug(f"Dependency 설치 - 이미 설치됨 : {dep['name']}") - break - else: - logger.debug(f"Dependency 설치 : {dep['home']}") - LogicPlugin.plugin_install_by_api(dep['home'], dep.get('zip_url'), dep.get('zip_filename')) - #command = ['git', '-C', custom_path, 'clone', dep['home'], '--depth', '1'] - #ret = Util.execute_command(command) - ret['ret'] = 'success' - ret['log'] = [u'정상적으로 설치하였습니다. 재시작시 적용됩니다.', log] - ret['log'] = '
'.join(ret['log']) - - - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - ret['ret'] = 'exception' - ret['log'] = str(exception) - - - return ret - \ No newline at end of file diff --git a/lib/system/logic_selenium.py b/lib/system/logic_selenium.py deleted file mode 100644 index 4472a42..0000000 --- a/lib/system/logic_selenium.py +++ /dev/null @@ -1,397 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################### -# python -import os -import traceback -import logging -import platform -import time -import base64 - -# third-party -from flask import Blueprint, request, Response, send_file, render_template, redirect, jsonify - -try: - from selenium import webdriver - from selenium.webdriver.support.ui import WebDriverWait - from PIL import Image - Image.MAX_IMAGE_PIXELS = None -except: - pass -from io import BytesIO - -# sjva 공용 - -from framework import path_app_root, path_data - -# 패키지 -from .plugin import logger, package_name -from .model import ModelSetting - -######################################################### -#apk --no-cache add --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing firefox -#https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-linux64.tar.gz -#curl -s -L "$url" | tar -xz - -class SystemLogicSelenium(object): - chrome_driver = None - chrome_driver_list = [] - - @staticmethod - def process_ajax(sub, req): - try: - if sub == 'selenium_test_go': - driver = SystemLogicSelenium.get_driver() - driver.get(req.form['url']) - return jsonify('success') - elif sub == 'capture': - driver = SystemLogicSelenium.get_driver() - img = Image.open(BytesIO((driver.get_screenshot_as_png()))) - - timestamp = time.time() - timestamp = str(timestamp).split('.')[0] - tmp = os.path.join(path_data, 'tmp', '%s.png' % timestamp) - img.save(tmp) - from system.model import ModelSetting as SystemModelSetting - ddns = SystemModelSetting.get('ddns') - url = '%s/open_file%s' % (ddns, tmp) - logger.debug(url) - ret = {} - ret['ret'] = 'success' - ret['data'] = url - return jsonify(ret) - elif sub == 'full_capture': - driver = SystemLogicSelenium.get_driver() - img = SystemLogicSelenium.full_screenshot(driver) - - timestamp = time.time() - timestamp = str(timestamp).split('.')[0] - tmp = os.path.join(path_data, 'tmp', '%s.png' % timestamp) - img.save(tmp) - return send_file(tmp, mimetype='image/png') - elif sub == 'cookie': - driver = SystemLogicSelenium.get_driver() - data = driver.get_cookies() - return jsonify(data) - elif sub == 'daum_capcha': - daum_capcha = req.form['daum_capcha'] - driver = SystemLogicSelenium.get_driver() - #driver.find_element_by_xpath('//div[@class="secret_viewer"]/p/img').screenshot("captcha.png") - driver.find_element_by_xpath('//input[@id="answer"]').send_keys(daum_capcha) - driver.find_element_by_xpath('//input[@value="%s"]' % u'확인').click() - return jsonify({'ret':'success'}) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return jsonify('exception') - - @staticmethod - def get_pagesoruce_by_selenium(url, wait_xpath, retry=True): - try: - logger.debug('get_pagesoruce_by_selenium:%s %s', url, wait_xpath) - driver = SystemLogicSelenium.get_driver() - #logger.debug('driver : %s', driver) - driver.get(url) - - WebDriverWait(driver, 10).until(lambda driver: driver.find_element_by_xpath(wait_xpath)) - #import time - #driver.save_screenshot('%s.png' % time.time()) - #logger.debug('return page_source') - return driver.page_source - except Exception as exception: - #logger.debug(driver.page_source) - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - SystemLogicSelenium.close_driver() - #SystemLogicSelenium.chrome_driver = None - if retry: - return SystemLogicSelenium.get_pagesoruce_by_selenium(url, wait_xpath, retry=False) - - # 1회성 - @staticmethod - def get_driver(chrome_options=None): - try: - if SystemLogicSelenium.chrome_driver is None: - SystemLogicSelenium.chrome_driver = SystemLogicSelenium.inner_create_driver(chrome_options) - return SystemLogicSelenium.chrome_driver - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - # 플러그인이 점유 - @staticmethod - def create_driver(chrome_options=None): - try: - driver = SystemLogicSelenium.inner_create_driver(chrome_options) - if driver is not None: - SystemLogicSelenium.chrome_driver_list.append(driver) - return driver - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - @staticmethod - def close_driver(): - try: - #if SystemLogicSelenium.chrome_driver is not None: - # SystemLogicSelenium.chrome_driver.quit() - # SystemLogicSelenium.chrome_driver = None - if SystemLogicSelenium.chrome_driver is not None: - try: SystemLogicSelenium.chrome_driver.close() - except: pass - time.sleep(2) - try: SystemLogicSelenium.chrome_driver.quit() - except: pass - SystemLogicSelenium.chrome_driver = None - - - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - @staticmethod - def inner_create_driver(chrome_options): - try: - driver = None - remote_url = ModelSetting.get('selenium_remote_url') - if remote_url.endswith('/wd/hub/'): - remote_url = remote_url[:-1] - if remote_url != '': - if chrome_options is None: - chrome_options = webdriver.ChromeOptions() - tmp = ModelSetting.get_list('selenium_remote_default_option') - for t in tmp: - chrome_options.add_argument(t) - driver = webdriver.Remote(command_executor=remote_url, desired_capabilities=chrome_options.to_capabilities()) - driver.set_window_size(1920, 1080) - logger.debug('Using Remote :%s', driver) - else: - path_chrome = os.path.join(path_app_root, 'bin', platform.system(), 'chromedriver') - if platform.system() == 'Windows': - path_chrome += '.exe' - if chrome_options is None: - chrome_options = webdriver.ChromeOptions() - tmp = ModelSetting.get_list('selenium_binary_default_option') - for t in tmp: - chrome_options.add_argument(t) - driver = webdriver.Chrome(path_chrome, chrome_options=chrome_options) - logger.debug('Using local bin :%s', driver) - if driver is not None: - return driver - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - @staticmethod - def plugin_unload(): - try: - SystemLogicSelenium.close_driver() - #logger.debug(SystemLogicSelenium.chrome_driver) - #if SystemLogicSelenium.chrome_driver is not None: - # SystemLogicSelenium.chrome_driver.quit() - # logger.debug(SystemLogicSelenium.chrome_driver) - - for tmp in SystemLogicSelenium.chrome_driver_list: - if tmp is not None: - tmp.quit() - - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - @staticmethod - def get_text_excluding_children(driver, element): - return driver.execute_script(""" - return jQuery(arguments[0]).contents().filter(function() { - return this.nodeType == Node.TEXT_NODE; - }).text(); - """, element) - - @staticmethod - def full_screenshot(driver, low_offset = 0): - try: - # initiate value - #save_path = save_path + '.png' if save_path[-4::] != '.png' else save_path - img_li = [] # to store image fragment - offset = 0 # where to start - - # js to get height - height = driver.execute_script('return Math.max(' - 'document.documentElement.clientHeight, window.innerHeight);') - #height = height - low_offset - # js to get the maximum scroll height - # Ref--> https://stackoverflow.com/questions/17688595/finding-the-maximum-scroll-position-of-a-page - max_window_height = driver.execute_script('return Math.max(' - 'document.body.scrollHeight, ' - 'document.body.offsetHeight, ' - 'document.documentElement.clientHeight, ' - 'document.documentElement.scrollHeight, ' - 'document.documentElement.offsetHeight);') - - # looping from top to bottom, append to img list - # Ref--> https://gist.github.com/fabtho/13e4a2e7cfbfde671b8fa81bbe9359fb - - while offset < max_window_height: - - # Scroll to height - driver.execute_script(""" - window.scrollTo(0, arguments[0]); - """, offset) - img = Image.open(BytesIO((driver.get_screenshot_as_png()))) - - if low_offset != 0: - img = img.crop((0, 0, img.width, img.height-low_offset)) # defines crop points - - img_li.append(img) - offset += height - logger.debug('offset : %s / %s', offset, max_window_height) - - # Stitch image into one - # Set up the full screen frame - img_frame_height = sum([img_frag.size[1] for img_frag in img_li]) - img_frame = Image.new('RGB', (img_li[0].size[0], img_frame_height)) - offset = 0 - for img_frag in img_li: - img_frame.paste(img_frag, (0, offset)) - offset += img_frag.size[1] - logger.debug('paste offset : %s ', offset) - #img_frame.save(save_path) - #return - return img_frame - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - @staticmethod - def remove_element(driver, element): - driver.execute_script(""" - var element = arguments[0]; - element.parentNode.removeChild(element); - """, element) - - - - ###################################################################### - @staticmethod - def __get_downloaded_files(driver=None): - if driver is None: - driver = SystemLogicSelenium.get_driver() - if not driver.current_url.startswith("chrome://downloads"): - driver.get("chrome://downloads/") - #driver.implicitly_wait(4) - return driver.execute_script( \ - "return downloads.Manager.get().items_ " - " .filter(e => e.state === 'COMPLETE') " - " .map(e => e.filePath || e.file_path); " ) - - - - @staticmethod - def get_file_content(path, driver=None): - if driver is None: - driver = SystemLogicSelenium.get_driver() - - elem = driver.execute_script( \ - "var input = window.document.createElement('INPUT'); " - "input.setAttribute('type', 'file'); " - "input.hidden = true; " - "input.onchange = function (e) { e.stopPropagation() }; " - "return window.document.documentElement.appendChild(input); " ) - - elem._execute('sendKeysToElement', {'value': [ path ], 'text': path}) - - result = driver.execute_async_script( \ - "var input = arguments[0], callback = arguments[1]; " - "var reader = new FileReader(); " - "reader.onload = function (ev) { callback(reader.result) }; " - "reader.onerror = function (ex) { callback(ex.message) }; " - "reader.readAsDataURL(input.files[0]); " - "input.remove(); " - , elem) - - if not result.startswith('data:') : - raise Exception("Failed to get file content: %s" % result) - - return base64.b64decode(result[result.find('base64,') + 7:]) - - - @staticmethod - def get_downloaded_files(driver=None): - if driver is None: - driver = SystemLogicSelenium.get_driver() - - #files = WebDriverWait(driver, 20, 1).until(SystemLogicSelenium.__get_downloaded_files) - files = SystemLogicSelenium.__get_downloaded_files() - return files - - @staticmethod - def waitUntilDownloadCompleted(maxTime=600, driver=None): - if driver is None: - driver = SystemLogicSelenium.get_driver() - driver.execute_script("window.open()") - # switch to new tab - driver.switch_to.window(driver.window_handles[-1]) - # navigate to chrome downloads - driver.get('chrome://downloads') - # define the endTime - endTime = time.time() + maxTime - while True: - try: - # get the download percentage - downloadPercentage = driver.execute_script( - "return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#progress').value") - # check if downloadPercentage is 100 (otherwise the script will keep waiting) - if downloadPercentage == 100: - # exit the method once it's completed - return downloadPercentage - except: - pass - # wait for 1 second before checking the percentage next time - time.sleep(1) - # exit method if the download not completed with in MaxTime. - if time.time() > endTime: - break - -""" - - -driver = webdriver.Chrome(desired_capabilities=capabilities_chrome) -#driver = webdriver.Remote('http://127.0.0.1:5555/wd/hub', capabilities_chrome) - -# download a pdf file -driver.get("https://www.mozilla.org/en-US/foundation/documents") -driver.find_element_by_css_selector("[href$='.pdf']").click() - -# list all the completed remote files (waits for at least one) -files = WebDriverWait(driver, 20, 1).until(get_downloaded_files) - -# get the content of the first file remotely -content = get_file_content(driver, files[0]) - -# save the content in a local file in the working directory -with open(os.path.basename(files[0]), 'wb') as f: - f.write(content) - - -capabilities_chrome = { \ - 'browserName': 'chrome', - # 'proxy': { \ - # 'proxyType': 'manual', - # 'sslProxy': '50.59.162.78:8088', - # 'httpProxy': '50.59.162.78:8088' - # }, - 'goog:chromeOptions': { \ - 'args': [ - ], - 'prefs': { \ - # 'download.default_directory': "", - # 'download.directory_upgrade': True, - 'download.prompt_for_download': False, - 'plugins.always_open_pdf_externally': True, - 'safebrowsing_for_trusted_sources_enabled': False - } - } - } -""" \ No newline at end of file diff --git a/lib/system/logic_site.py b/lib/system/logic_site.py deleted file mode 100644 index bd30b3a..0000000 --- a/lib/system/logic_site.py +++ /dev/null @@ -1,233 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################### -# python -import os -import traceback -import logging -import platform -import time - -# third-party -from flask import Blueprint, request, Response, send_file, render_template, redirect, jsonify - - - -from framework import F, path_app_root, path_data, socketio, scheduler -from tool_base import d - - -# 패키지 -from .plugin import logger, package_name -from .model import ModelSetting - - -class SystemLogicSite(object): - # 매번 split 하기 머해서 - daum_cookie = None - - @staticmethod - def process_ajax(sub, req): - try: - ret = {} - if sub == 'site_daum_test': - site_daum_test = req.form['site_daum_test'] - ModelSetting.set('site_daum_test', site_daum_test) - from framework.common.daum import DaumTV, MovieSearch - ret['TV'] = DaumTV.get_daum_tv_info(site_daum_test) - if ret['TV'] is not None and 'episode_list' in ret['TV']: - del ret['TV']['episode_list'] - ret['MOVIE'] = MovieSearch.search_movie(site_daum_test, -1) - return jsonify(ret) - elif sub == 'site_daum_cookie_refresh': - ret = SystemLogicSite.get_daum_cookie_by_selenium(notify=True) - return jsonify(ret) - elif sub == 'scheduler': - go = req.form['scheduler'] - if go == 'true': - SystemLogicSite.scheduler_start() - else: - SystemLogicSite.scheduler_stop() - return jsonify(go) - elif sub == 'tving_login': - try: - from support.site.tving import SupportTving - token = SupportTving().do_login(req.form['tving_id'], req.form['tving_pw'], req.form['tving_login_type']) - if token is None: - ret['ret'] = False - else: - ret['ret'] = True - ret['token'] = token - return jsonify(ret) - except Exception as e: - logger.error('Exception:%s', e) - logger.error(traceback.format_exc()) - elif sub == 'tving_deviceid': - try: - from support.site.tving import SupportTving - device_list = SupportTving(token=req.form['tving_token']).get_device_list() - if device_list is None: - ret['ret'] = False - else: - ret['ret'] = True - ret['device_list'] = device_list - return jsonify(ret) - except Exception as e: - logger.error('Exception:%s', e) - logger.error(traceback.format_exc()) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - ret['ret'] = False - ret['log'] = str(traceback.format_exc()) - return jsonify(ret) - - @staticmethod - def process_api(sub, req): - ret = {} - try: - if sub == 'daum_cookie': - return ModelSetting.get('site_daum_cookie') - - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - ret['ret'] = 'exception' - ret['data'] = str(exception) - return jsonify(ret) - ########################################################################## - - @staticmethod - def plugin_load(): - SystemLogicSite.create_tving_instance() - return - SystemLogicSite.get_daum_cookies(force=True) - if ModelSetting.get_bool('site_daum_auto_start'): - SystemLogicSite.scheduler_start() - - @staticmethod - def create_tving_instance(): - from support.site.tving import SupportTving - proxy = None - if ModelSetting.get_bool('site_tving_use_proxy'): - proxy = ModelSetting.get('site_tving_proxy_url') - SupportTving.ins = SupportTving(token=ModelSetting.get('site_tving_token'), proxy=proxy, deviceid=ModelSetting.get('site_tving_deviceid'), uuid=ModelSetting.get('site_tving_uuid')) - - - - @staticmethod - def scheduler_start(): - job = Job(package_name, '%s_site' % package_name, ModelSetting.get('site_daum_interval'), SystemLogicSite.scheduler_function, u"Daum cookie refresh", False) - scheduler.add_job_instance(job) - - @staticmethod - def scheduler_stop(): - scheduler.remove_job('%s_site' % package_name) - - - @staticmethod - def scheduler_function(): - try: - data = SystemLogicSite.get_daum_cookie_by_selenium() - if data['ret']: - ModelSetting.set('site_daum_cookie', data['data']) - SystemLogicSite.get_daum_cookies(force=True) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - - @staticmethod - def get_daum_cookie_by_selenium(notify=False): - try: - ret = {} - ret['ret'] = False - from .logic_selenium import SystemLogicSelenium - if notify: - data = {'type':'success', 'msg' : u'사이트 접속중입니다.'} - socketio.emit("notify", data, namespace='/framework', broadcast=True) - SystemLogicSelenium.get_pagesoruce_by_selenium('https://www.daum.net', '//*[@id="daumFoot"]/div/a[1]/img') - if notify: - data = {'type':'success', 'msg' : u'쿠키 확인'} - socketio.emit("notify", data, namespace='/framework', broadcast=True) - driver = SystemLogicSelenium.get_driver() - cookies = driver.get_cookies() - for tmp in cookies: - if tmp['name'] == 'TIARA': - ret['ret'] = True - ret['data'] = 'TIARA=%s' % tmp['value'] - return ret - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return ret - - - - @staticmethod - def get_daum_cookies(force=False): - try: - if SystemLogicSite.daum_cookie is None or force: - ret = {} - tmp = ModelSetting.get('site_daum_cookie') - tmps = tmp.split(';') - for t in tmps: - t2 = t.split('=') - if len(t2) == 2: - ret[t2[0]] = t2[1] - SystemLogicSite.daum_cookie = ret - return SystemLogicSite.daum_cookie - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return {'TIARA':'gaXEIPluo-wWAFlwZN6l8gN3yzhkoo_piP.Kymhuy.6QBt4Q6.cRtxbKDaWpWajcyteRHzrlTVpJRxLjwLoMvyYLVi_7xJ1L'} - - - daum_headers = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36', - 'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', - 'Accept-Language' : 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7', - } - - @classmethod - def get_tree_daum(cls, url, post_data=None): - from lxml import html - from framework import SystemModelSetting - text = cls.get_text_daum(url, post_data=post_data) - if text is None: - return - return html.fromstring(text) - - @classmethod - def get_text_daum(cls, url, post_data=None): - from system.logic_site import SystemLogicSite - from framework import SystemModelSetting - res = cls.get_response(url, proxy_url=SystemModelSetting.get('site_daum_proxy'), headers=SystemLogicSite.daum_headers, post_data=post_data, cookies=SystemLogicSite.get_daum_cookies()) - return res.text - - - @classmethod - def get_response_daum(cls, url, post_data=None): - from system.logic_site import SystemLogicSite - from framework import SystemModelSetting - res = cls.get_response(url, proxy_url=SystemModelSetting.get('site_daum_proxy'), headers=SystemLogicSite.daum_headers, post_data=post_data, cookies=SystemLogicSite.get_daum_cookies()) - return res - - - @classmethod - def get_response(cls, url, proxy_url=None, headers=None, post_data=None, cookies=None): - import requests - proxies = None - if proxy_url is not None and proxy_url != '': - proxies = {"http" : proxy_url, "https" : proxy_url} - if headers is None: - headers = SystemLogicSite.default_headers - if post_data is None: - #logger.warning(d(headers)) - #logger.warning(d(proxies)) - #logger.warning(d(cookies)) - - res = requests.get(url, headers=headers, proxies=proxies, cookies=cookies) - else: - res = requests.post(url, headers=headers, proxies=proxies, data=post_data, cookies=cookies) - return res \ No newline at end of file diff --git a/lib/system/logic_telegram_bot.py b/lib/system/logic_telegram_bot.py deleted file mode 100644 index bdd4cf9..0000000 --- a/lib/system/logic_telegram_bot.py +++ /dev/null @@ -1,78 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################### -# python -import os -import traceback -import logging -import platform -import time - -# third-party -from flask import Blueprint, request, Response, send_file, render_template, redirect, jsonify - - - -from framework import F, frame, app, path_app_root, path_data, scheduler -from tool_base import ToolBaseNotify -# 패키지 -from .plugin import logger, package_name -from .model import ModelSetting - - -class SystemLogicTelegramBot(object): - @staticmethod - def process_ajax(sub, req): - try: - if sub == 'telegram_test': - ret = ToolBaseNotify.send_telegram_message(req.form['text'], bot_token=req.form['bot_token'], chat_id=req.form['chat_id']) - return jsonify(ret) - elif sub == 'discord_test': - ret = ToolBaseNotify.send_discord_message(req.form['text'], webhook_url=req.form['url']) - return jsonify(ret) - elif sub == 'advanced_test': - ret = ToolBaseNotify.send_advanced_message(req.form['text'], policy=req.form['policy'], message_id=req.form['message_id']) - return jsonify(ret) - elif sub == 'scheduler': - go = request.form['scheduler'] - logger.debug('scheduler :%s', go) - if go == 'true': - SystemLogicTelegramBot.scheduler_start() - else: - SystemLogicTelegramBot.scheduler_stop() - return jsonify(go) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return jsonify('exception') - - @staticmethod - def plugin_load(): - try: - if frame.config['run_celery']: - return - - if ModelSetting.get_bool('telegram_bot_auto_start'): - SystemLogicTelegramBot.scheduler_start() - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - @staticmethod - def scheduler_start(): - try: - interval = 60*24 - job = Job(package_name, '%s_telegram_bot' % (package_name), 9999, SystemLogicTelegramBot.scheduler_function, u"시스템 - 텔레그램 봇", False) - scheduler.add_job_instance(job) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - @staticmethod - def scheduler_function(): - try: - bot_token = ModelSetting.get('telegram_bot_token') - from framework.common.telegram_bot import TelegramBot - TelegramBot.start(bot_token) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) \ No newline at end of file diff --git a/lib/system/logic_terminal.py b/lib/system/logic_terminal.py deleted file mode 100644 index cdb1127..0000000 --- a/lib/system/logic_terminal.py +++ /dev/null @@ -1,62 +0,0 @@ -try: - import yaml - a = yaml.FullLoader -except: - from framework import app - import os - try: os.system(f"{app.config['config']['pip']} install --upgrade pyyaml") - except: pass - -import os, sys, traceback, json -from framework import path_data -from flask import request, render_template, redirect, jsonify -from .plugin import logger - - -class SystemLogicTerminal(object): - yaml_path = os.path.join(path_data, 'db', 'terminal.yaml') - - @classmethod - def process_ajax(cls, sub, req): - logger.error(sub) - logger.error(req) - try: - if sub == 'get_info': - ret = cls.get_info() - elif sub == 'run': - data = cls.get_info() - idx = int(req.form['index']) - from terminal.logic_terminal import LogicTerminal - LogicTerminal.wait_input(data['commands'][idx]['command']) - return jsonify({'ret':'success'}) - return jsonify(ret) - except Exception as e: - logger.error(f'Exception: {str(e)}') - logger.error(traceback.format_exc()) - - @classmethod - def get_info(cls): - if os.path.exists(cls.yaml_path) == False: - with open(cls.yaml_path, 'w', encoding='utf8') as f: - f.write(yaml_templete) - with open(cls.yaml_path, 'r', encoding='utf8') as f: - info = yaml.load(f, Loader=yaml.FullLoader) - return info - - - - -yaml_templete = ''' - -commands: - - title: SJVA 데이터 폴더별 크기 확인 - command: | - cd ./data - du -h -d 1 - - - title: SJVA 도커 재시작 - command: | - ssh -i MY.pem ubuntu@172.17.0.1 - sudo docker restart sjva - -''' \ No newline at end of file diff --git a/lib/system/logic_tool_crypt.py b/lib/system/logic_tool_crypt.py deleted file mode 100644 index dac3b3a..0000000 --- a/lib/system/logic_tool_crypt.py +++ /dev/null @@ -1,52 +0,0 @@ -import traceback -from flask import jsonify -from framework import app - -# 패키지 -from .plugin import package_name, logger -from .model import ModelSetting - -class SystemLogicToolDecrypt(object): - @staticmethod - def process_ajax(sub, req): - try: - if sub == 'crypt_test': - ret = SystemLogicToolDecrypt.crypt_test(req) - return jsonify(ret) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - ########################################################################## - - @staticmethod - def crypt_test(req): - try: - mode = req.form['mode'] - word = req.form['word'] - - logger.debug(mode) - logger.debug(word) - from tool_base import ToolAESCipher - mykey = None - if ModelSetting.get_bool('tool_crypt_use_user_key'): - mykey = ModelSetting.get('tool_crypt_user_key').lower().zfill(32) - if app.config['config']['is_py2']: - mykey = mykey.encode('utf8') - if len(mykey) > 32: - mykey = mykey[:32] - logger.debug(mykey) - - if mode == 'encrypt': - ModelSetting.set('tool_crypt_encrypt_word', u'%s' % word) - ret = {'ret':'success', 'data':ToolAESCipher.encrypt(word, mykey=mykey)} - elif mode == 'decrypt': - ModelSetting.set('tool_crypt_decrypt_word', u'%s' % word) - ret = {'ret':'success', 'data':ToolAESCipher.decrypt(word, mykey=mykey).decode()} - - logger.debug(ret) - return ret - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return {'ret':'exception', 'data':str(exception)} diff --git a/lib/system/mod_setting.py b/lib/system/mod_setting.py index 979e240..649a171 100644 --- a/lib/system/mod_setting.py +++ b/lib/system/mod_setting.py @@ -1,8 +1,10 @@ import random import string +import time -from support import SupportDiscord, SupportFile, SupportTelegram -from tool.modal_command import ToolModalCommand +from support import (SupportDiscord, SupportFile, SupportSubprocess, + SupportTelegram) +from tool import ToolModalCommand from .setup import * @@ -35,7 +37,7 @@ class ModuleSetting(PluginModuleBase): 'notify.yaml': '', #직접 사용하지 않으나 저장 편의상. 'command_text': '', 'celery_start_by_web': 'False', #웹 실행시 celery 실행 - 'celery_start_command': "celery -A flaskfarm.main.celery worker --loglevel=info --pool=gevent --concurrency=2 --config_filepath={F.config['config_filepath']} --running_type=native", + 'celery_start_command': "celery -A flaskfarm.main.celery worker --workdir={F.config['path_working']} --loglevel=info --pool=gevent --concurrency=2 --config_filepath={F.config['config_filepath']} --running_type=native", } @@ -65,7 +67,6 @@ class ModuleSetting(PluginModuleBase): elif page == 'celery': arg['use_celery'] = F.config['use_celery'] arg['running_type'] = F.config['running_type'] - return render_template(f'{__package__}_{name}_{page}.html', arg=arg) except Exception as e: P.logger.error(f'Exception:{str(e)}') @@ -122,13 +123,13 @@ class ModuleSetting(PluginModuleBase): ret['msg'] = arg1 pass elif command == 'celery_execute': - tmp = arg1.replace("{F.config['config_filepath']}", F.config['config_filepath']).replace('{F.config["config_filepath"]}', F.config['config_filepath']) - cmd = [ - ['msg', f'명령 : {tmp}'], - ['msg', ''], - tmp.split(' '), - ] - ToolModalCommand.start("Celery 실행", cmd) + self.celery_execute(arg1, mode='foreground') + elif command == 'celery_execute_back': + self.celery_execute(arg1, mode='background') + ret['msg'] = '실행했습니다.' + elif command == 'celery_test': + return self.__celery_test() + return jsonify(ret) @@ -136,9 +137,8 @@ class ModuleSetting(PluginModuleBase): try: if F.config['run_flask'] == False: return - F.logger.info(f"arg_repeat : {F.config['arg_repeat']}") - F.logger.info(f"arg_repeat : {F.config['arg_repeat']}") - + if SystemModelSetting.get_bool('celery_start_by_web'): + self.celery_execute() if F.config['arg_repeat'] == 0 or SystemModelSetting.get('system_start_time') == '': SystemModelSetting.set('system_start_time', datetime.now().strftime('%Y-%m-%d %H:%M:%S')) SystemModelSetting.set('repeat', str(F.config['arg_repeat'])) @@ -161,15 +161,17 @@ class ModuleSetting(PluginModuleBase): from tool import ToolNotify msg = f"시스템이 시작되었습니다.\n재시작: {F.config['arg_repeat']}" ToolNotify.send_message(msg, message_id='system_start') + + except Exception as e: P.logger.error(f'Exception:{str(e)}') P.logger.error(traceback.format_exc()) def plugin_unload(self): - ToolModalCommand.process_close() + ToolModalCommand.modal_close() def setting_save_after(self, change_list): - if 'theme' in change_list: + if 'theme' in change_list or 'web_title' in change_list: F.socketio.emit("refresh", {}, namespace='/framework', broadcast=True) elif 'notify.yaml' in change_list: SupportFile.write_file(F.config['notify_yaml_filepath'], SystemModelSetting.get('notify.yaml')) @@ -196,3 +198,53 @@ class ModuleSetting(PluginModuleBase): scheduler.add_job_instance(job_instance, run=False) + def celery_execute(self, command=None, mode='background'): + if command == None: + command = SystemModelSetting.get('celery_start_command') + command = command.replace("{F.config['config_filepath']}", F.config['config_filepath']).replace('{F.config["config_filepath"]}', F.config['config_filepath']).replace("{F.config['path_working']}", F.config['path_working']).replace('{F.config["path_working"]}', F.config['path_working']) + if mode == 'foreground': + cmd = [ + ['msg', f'명령 : {command}'], + command.split(' '), + ] + ToolModalCommand.start("Celery 실행", cmd) + elif mode == 'background': + SupportSubprocess(command).start(join=False) + + + def __celery_test(self): + if F.config['use_celery']: + from celery import Celery + from celery.exceptions import NotRegistered, TimeoutError + data = {} + try: + result = self.celery_test.apply_async() + try: + tmp = result.get(timeout=5, propagate=True) + except Exception as e: + P.logger.error(f'Exception:{str(e)}') + P.logger.error(traceback.format_exc()) + data['ret'] = 'success' + data['msg'] = tmp + except TimeoutError: + data['ret'] = 'danger' + data['msg'] = 'celery가 동작중이 아니거나 모든 Worker가 작업중입니다.' + except NotRegistered: + data['ret'] = 'danger' + data['msg'] = 'Not Registered' + else: + data['ret'] = 'danger' + data['msg'] = 'celery 실행환경이 아닙니다.' + P.logger.debug(d(data)) + return data + + #@staticmethod + @celery.task + def celery_test(): + try: + time.sleep(1) + data = '정상입니다. 이 메시지는 celery 에서 반환됩니다. ' + return data + except Exception as e: + P.logger.error(f'Exception:{str(e)}') + P.logger.error(traceback.format_exc()) diff --git a/lib/system/model.py b/lib/system/model.py deleted file mode 100644 index f0805d2..0000000 --- a/lib/system/model.py +++ /dev/null @@ -1,8 +0,0 @@ -import traceback -from framework import db, get_logger -from framework.util import Util - -logger = get_logger(__package__) - -from plugin.model_setting import get_model_setting -ModelSetting = get_model_setting(__package__, logger) diff --git a/lib/system/plugin.py b/lib/system/plugin.py deleted file mode 100644 index 5c6db16..0000000 --- a/lib/system/plugin.py +++ /dev/null @@ -1,543 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################### -# python -import json -import logging -import os -import platform -import threading -import time -import traceback - -# third-party -import requests -from flask import (Blueprint, Response, jsonify, redirect, render_template, - request, send_file, stream_with_context) -from flask_login import login_required -# sjva 공용 -from framework import (app, check_api, frame, get_logger, # , celery - path_app_root, path_data, scheduler, socketio) -from support import SingletonClass - -# 로그 -package_name = __name__.split('.')[0] -logger = get_logger(__package__) - -# 패키지 -from .logic import SystemLogic -from .logic_auth import SystemLogicAuth -from .logic_command import SystemLogicCommand -from .logic_command2 import SystemLogicCommand2 -# celery 때문에 import -from .logic_env import SystemLogicEnv -from .logic_notify import SystemLogicNotify -from .logic_plugin import LogicPlugin -from .logic_selenium import SystemLogicSelenium -from .logic_site import SystemLogicSite -from .logic_telegram_bot import SystemLogicTelegramBot -from .logic_terminal import SystemLogicTerminal -from .logic_tool_crypt import SystemLogicToolDecrypt -from .model import ModelSetting - -######################################################### - - -######################################################### -# 플러그인 공용 -######################################################### -blueprint = Blueprint(package_name, package_name, url_prefix='/%s' % package_name, template_folder='templates') - -menu = { - 'uri' : package_name, - 'name': '설정', - 'list': [ - { - 'uri': 'setting', - 'name': '일반설정', - 'list': [ - {'uri': 'basic', 'name': '기본'}, - {'uri': 'auth', 'name': '인증'}, - {'uri': 'env', 'name': '시스템'}, - {'uri': 'notify', 'name': '알림'}, - {'uri': 'telegram_bot', 'name': '텔레그램 봇'}, - {'uri': 'selenium', 'name': 'Selenium'}, - {'uri': 'site', 'name': 'Site'}, - {'uri': 'memo', 'name': '메모'}, - {'uri': 'terminal', 'name': 'Terminal'}, - ], - }, - { - 'uri': 'plugin', - 'name': '플러그인' - }, - { - 'uri': 'tool', - 'name': 'Tool', - 'list': [{'uri': 'crypt', 'name': '암호화'}] - }, - { - 'uri': 'log', - 'name': '로그' - } - ] -} - - - -#if platform.system() == 'Windows': -# del menu['sub2']['setting'][-1] - - -def plugin_load(): - logger.debug('plugin_load:%s', package_name) - SystemLogic.plugin_load() - SystemLogicTelegramBot.plugin_load() - SystemLogicSite.plugin_load() - -def plugin_unload(): - logger.debug('plugin_load:%s', package_name) - SystemLogicSelenium.plugin_unload() - SystemLogicCommand.plugin_unload() - SystemLogicCommand2.plugin_unload() - - -######################################################### -# WEB Menu -######################################################### -@blueprint.route('/') -def normal(): - return redirect('/%s/setting' % package_name) - -@login_required -def home(): - return render_template('info.html', arg=None) - -@blueprint.route('/', methods=['GET', 'POST']) -@login_required -def first_menu(sub): - #logger.debug('System SUB:%s', sub) - arg = None - if sub == 'home': - return render_template('%s_%s.html' % (package_name, sub), arg=None) - elif sub == 'setting': - return redirect('/%s/%s/basic' % (package_name, sub)) - elif sub == 'tool': - return redirect('/%s/%s/crypt' % (package_name, sub)) - elif sub == 'plugin': - arg = ModelSetting.to_dict() - arg['install'] = request.args.get('install', '') - if arg['install'] == 'flaskfilemanager': - arg['install'] = 'https://github.com/soju6jan/' + arg['install'] - try: - import flaskfilemanager - arg['install'] = '' - except: - pass - elif arg['install'] == 'flaskcode': - arg['install'] = 'https://github.com/soju6jan/' + arg['install'] - try: - import flaskcode - arg['install'] = '' - except: - pass - - - - return render_template('system_plugin.html', arg=arg) - elif sub == 'information': - return render_template('manual.html', sub=sub, arg='system.json') - elif sub == 'log': - log_files=os.listdir(os.path.join(path_data, 'log')) - log_files.sort() - log_list = [] - arg = {'package_name' : package_name, 'sub' : sub} - for x in log_files: - if x.endswith('.log'): - log_list.append(x) - arg['log_list'] = '|'.join(log_list) - arg['all_list'] = '|'.join(log_files) - arg['filename'] = '' - if 'filename' in request.form: - arg['filename'] = request.form['filename'] - logger.debug(arg) - return render_template('%s_%s.html' % (package_name, sub), arg=arg) - elif sub == 'restart': - restart() - return render_template('system_restart.html', sub=sub, referer=request.headers.get("Referer")) - elif sub == 'shutdown': - shutdown() - return render_template('system_restart.html', sub=sub, referer=request.headers.get("Referer")) - elif sub == 'telegram': - return redirect('/%s/%s/setting' % (package_name, sub)) - return render_template('sample.html', title='%s - %s' % (package_name, sub)) - - -@blueprint.route('//') -@login_required -def second_menu(sub, sub2): - try: - if sub == 'setting': - arg = ModelSetting.to_dict() - arg['sub'] = sub2 - if sub2 == 'basic': - arg['point'] = SystemLogic.point - return render_template('%s_%s_%s.html' % (package_name, sub, sub2), arg=arg) - elif sub2 in ['trans', 'selenium', 'notify']: - return render_template('%s_%s_%s.html' % (package_name, sub, sub2), arg=arg) - elif sub2 == 'auth': - arg['auth_result'] = SystemLogicAuth.get_auth_status() - return render_template('%s_%s_%s.html' % (package_name, sub, sub2), arg=arg) - elif sub2 == 'telegram_bot': - arg['scheduler'] = str(scheduler.is_include('%s_%s' % (package_name, sub2))) - arg['is_running'] = str(scheduler.is_running('%s_%s' % (package_name, sub2))) - return render_template('%s_%s_%s.html' % (package_name, sub, sub2), arg=arg) - elif sub2 == 'env': - arg['export'] = SystemLogicEnv.load_export() - if arg['export'] is None: - arg['export'] = u'export.sh 파일이 없습니다.' - return render_template('%s_%s_%s.html' % (package_name, sub, sub2), arg=arg) - elif sub2 == 'site': - arg['scheduler'] = str(scheduler.is_include('%s_%s' % (package_name, sub2))) - arg['is_running'] = str(scheduler.is_running('%s_%s' % (package_name, sub2))) - from system.model import ModelSetting as SystemModelSetting - arg['site_get_daum_cookie_url'] = '{ddns}/{package_name}/api/{sub2}/daum_cookie'.format(ddns=SystemModelSetting.get('ddns'), package_name=package_name, sub2=sub2) - if SystemModelSetting.get_bool('auth_use_apikey'): - arg['site_get_daum_cookie_url'] += '?apikey={apikey}'.format(apikey=SystemModelSetting.get('auth_apikey')) - return render_template('%s_%s_%s.html' % (package_name, sub, sub2), arg=arg) - elif sub2 == 'memo': - return render_template('%s_%s_%s.html' % (package_name, sub, sub2), arg=arg) - elif sub2 == 'terminal': - arg['yaml_path'] = SystemLogicTerminal.yaml_path.replace(path_app_root, '') - return render_template('%s_%s_%s.html' % (package_name, sub, sub2), arg=arg) - elif sub == 'tool': - arg = ModelSetting.to_dict() - arg['sub'] = sub2 - if sub2 == 'crypt': - return render_template('%s_%s_%s.html' % (package_name, sub, sub2), arg=arg) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - - - -######################################################### -# For UI -######################################################### -@blueprint.route('/ajax//', methods=['GET', 'POST']) -@login_required -def second_ajax(sub, sub2): - logger.debug('System AJAX sub:%s', sub) - try: - if sub == 'auth': - from .logic_auth import SystemLogicAuth - return SystemLogicAuth.process_ajax(sub2, request) - elif sub == 'selenium': - return SystemLogicSelenium.process_ajax(sub2, request) - elif sub == 'notify': - return SystemLogicNotify.process_ajax(sub2, request) - elif sub == 'telegram_bot': - return SystemLogicTelegramBot.process_ajax(sub2, request) - elif sub == 'env': - return SystemLogicEnv.process_ajax(sub2, request) - elif sub == 'site': - return SystemLogicSite.process_ajax(sub2, request) - elif sub == 'crypt': - return SystemLogicToolDecrypt.process_ajax(sub2, request) - elif sub == 'terminal': - return SystemLogicTerminal.process_ajax(sub2, request) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - -@blueprint.route('/ajax/', methods=['GET', 'POST']) -@login_required -def ajax(sub): - #logger.debug('System AJAX sub:%s', sub) - try: - if sub == 'info': - try: - ret = {} - ret['system'] = SystemLogic.get_info() - ret['scheduler'] = scheduler.get_job_list_info() - - #logger.debug(ret) - return jsonify(ret) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return jsonify() - elif sub == 'setting_save_system': - try: - ret = SystemLogic.setting_save_system(request) - return jsonify(ret) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - elif sub == 'setting_save': - ret = ModelSetting.setting_save(request) - SystemLogic.setting_save_after() - return jsonify(ret) - elif sub == 'ddns_test': - try: - url = request.form['ddns'] + '/version' - res = requests.get(url) - data = res.text - #data = res.json() - #logger.debug(data) - return jsonify(data) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - return jsonify('fail') - elif sub == 'celery_test': - try: - #result = add_together.delay(10, 20) - #print(result.wait()) - #return 'Welcome to my app!' - try: - import framework - framework.exit_code = 1 - socketio.stop() - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - #os.environ['SJVA_REPEAT_TYPE'] = 'update' - - - return jsonify() - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - elif sub == 'command_run': - try: - command_text = request.form['command_text'] - ret = SystemLogic.command_run(command_text) - return jsonify(ret) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - elif sub == 'get_link_list': - try: - link_json = SystemLogic.get_setting_value('link_json') - j = json.loads(link_json) - return jsonify(j) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - elif sub == 'link_save': - try: - link_data_str = request.form['link_data'] - #j = json.loads(link_data) - ret = SystemLogic.link_save(link_data_str) - return jsonify(ret) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - elif sub == 'plugin_list': - try: - return jsonify(LogicPlugin.get_plugin_list()) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - elif sub == 'plugin_install': - try: - #plugin_name = request.form['plugin_name'] - plugin_git = request.form['plugin_git'] - return jsonify(LogicPlugin.plugin_install_by_api(plugin_git, request.form.get('zip_url'), request.form.get('zip_filename'))) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - elif sub == 'plugin_uninstall': - try: - plugin_name = request.form['plugin_name'] - return jsonify(LogicPlugin.plugin_uninstall(plugin_name)) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - elif sub == 'recent_version': - ret = SystemLogic.get_recent_version() - ret = {'ret':ret, 'version':SystemLogic.recent_version} - return jsonify(ret) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - -@socketio.on('connect', namespace='/%s' % package_name) -def connect(): - try: - InfoProcess.instance().connect(request.sid) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - -@socketio.on('disconnect', namespace='/%s' % package_name) -def disconnect(): - try: - InfoProcess.instance().disconnect(request.sid) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - -@socketio.on('connect', namespace='/system_restart') -def connect_system_restart(): - try: - socketio.emit("on_connect", 'restart', namespace='/system_restart', broadcast=True) - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - -@socketio.on('disconnect', namespace='/system_restart') -def disconnect_system_restart(): - try: - pass - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - - - -######################################################### -# API -######################################################### - -@blueprint.route('/api/', methods=['GET', 'POST']) -@check_api -def first_api(sub): - try: - if sub == 'plugin_add': - plugin_git = request.form['plugin_git'] - from system.logic_plugin import LogicPlugin - ret = LogicPlugin.plugin_install_by_api(plugin_git, request.form.get('zip_url'), request.form.get('zip_filename')) - return jsonify(ret) - elif sub == 'restart': - logger.debug('web restart') - import system - system.restart() - return jsonify({'ret':'success'}) - elif sub == 'gds': - url = f"{app.config['DEFINE']['WEB_DIRECT_URL']}/sjva/gds2.php?type=file&id={request.args.get('id')}&user_id={ModelSetting.get('sjva_me_user_id')}&user_apikey={ModelSetting.get('auth_apikey')}" - data = requests.get(url).json()['data'] - logger.debug(data) - req_headers = dict(request.headers) - headers = {} - - if 'Range' not in req_headers or req_headers['Range'].startswith('bytes=0-'): - headers['Range'] = "bytes=0-1048576" - else: - headers['Range'] = req_headers['Range'] - headers['Authorization'] = f"Bearer {data['token']}" - headers['Connection'] = 'keep-alive' - - r = requests.get(data['url'], headers=headers, stream=True) - rv = Response(r.iter_content(chunk_size=1048576), r.status_code, content_type=r.headers['Content-Type'], direct_passthrough=True) - rv.headers.add('Content-Range', r.headers.get('Content-Range')) - return rv - elif sub == 'gds2': - url = f"{app.config['DEFINE']['WEB_DIRECT_URL']}/sjva/gds.php?type=file&id={request.args.get('id')}&user_id={ModelSetting.get('sjva_me_user_id')}&user_apikey={ModelSetting.get('auth_apikey')}" - data = requests.get(url).json()['data'] - logger.debug(data) - req_headers = dict(request.headers) - headers = {} - - headers['Range'] = f"bytes={request.args.get('range')}" - headers['Authorization'] = f"Bearer {data['token']}" - headers['Connection'] = 'keep-alive' - logger.warning(headers) - """ - response = redirect(data['url']) - headers = dict(response.headers) - headers.update({'Authorization': f"Bearer {data['token']}"}) - response.headers = headers - return response - - response.headers.add('Authorization', headers['Authorization']) - #response.headers['Location'] = data['url'] - return response - """ - - r = requests.get(data['url'], headers=headers, stream=True) - logger.warning(r.history) - #rv = Response(r.iter_content(chunk_size=10485760), r.status_code, content_type=r.headers['Content-Type'], direct_passthrough=True) - #rv.headers.add('Content-Range', r.headers.get('Content-Range')) - - rv = Response(r.iter_content(chunk_size=1048576), r.status_code, content_type=r.headers['Content-Type'], direct_passthrough=True) - rv.headers.add('Content-Range', r.headers.get('Content-Range')) - - logger.debug(rv.headers) - return rv - elif sub == 'gds_subtitle': - url = f"{app.config['DEFINE']['WEB_DIRECT_URL']}/sjva/gds2.php?type=file&id={request.args.get('id')}&user_id={ModelSetting.get('sjva_me_user_id')}&user_apikey={ModelSetting.get('auth_apikey')}" - data = requests.get(url).json()['data'] - logger.debug(data) - req_headers = dict(request.headers) - headers = {} - headers['Range'] = f"bytes={request.args.get('range')}" - headers['Authorization'] = f"Bearer {data['token']}" - headers['Connection'] = 'keep-alive' - logger.warning(headers) - r = requests.get(data['url'], headers=headers, stream=True) - logger.warning(r.history) - if r.encoding != None: - if r.encoding == 'ISO-8859-1': # 한글자막 인코딩 예외처리 - try: - text = r.content.decode('utf-8', "strict") - except Exception as e: - logger.error('Exception:%s', e) - logger.error(traceback.format_exc()) - text = r.content.decode('utf-8', "ignore") - else: - text = r.content.decode(r.encoding, "ignore") - else: - text = r.text - from framework.common.util import convert_srt_to_vtt as convSrt2Vtt - vtt = convSrt2Vtt(text) - r.headers['Content-Type'] = "text/vtt; charset=utf-8" - rv = Response(vtt, r.status_code, content_type=r.headers['Content-Type']) - rv.headers.add('Content-Disposition', 'inline; filename="subtitle.vtt"') - rv.headers.add('Content-Transfer-Encoding', 'binary') - logger.debug(rv.headers) - return rv - - - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - -@blueprint.route('/api//', methods=['GET', 'POST']) -@check_api -def second_api(sub, sub2): - try: - if sub == 'trans': - from .logic_trans import SystemLogicTrans - return SystemLogicTrans.process_api(sub2, request) - elif sub == 'site': - from .logic_site import SystemLogicSite - return SystemLogicSite.process_api(sub2, request) - - except Exception as exception: - logger.error('Exception:%s', exception) - logger.error(traceback.format_exc()) - - -@blueprint.route("/videojs", methods=['GET', 'POST']) -def videojs(): - data = {} - data['play_title'] = request.form['play_title'] - data['play_source_src'] = request.form['play_source_src'] - data['play_source_type'] = request.form['play_source_type'] - if 'play_subtitle_src' in request.form: - data['play_subtitle_src'] = request.form['play_subtitle_src'] - #logger.warning(data) - return render_template('videojs.html', data=data) diff --git a/lib/system/setup.py b/lib/system/setup.py index 08ec564..2fb6ee9 100644 --- a/lib/system/setup.py +++ b/lib/system/setup.py @@ -14,7 +14,6 @@ __menu = { {'uri': 'export', 'name': 'export.sh 파일'}, {'uri': 'celery', 'name': '비동기 작업(celery)'}, {'uri': 'notify', 'name': '알림'}, - ], }, { diff --git a/lib/system/templates/system_setting_celery.html b/lib/system/templates/system_setting_celery.html index 5a1843c..b779ecc 100644 --- a/lib/system/templates/system_setting_celery.html +++ b/lib/system/templates/system_setting_celery.html @@ -16,108 +16,45 @@ {{ macros.setting_input_textarea('celery_start_command', 'celery 실행 명령', desc=['', - '예: celery -A flaskfarm.main.celery worker --loglevel=info --pool=gevent --concurrency=2 --config_filepath="config.yaml파일경로" --running_type=native', + '예: celery -A flaskfarm.main.celery worker --workdir={F.config["path_working"]} --loglevel=info --pool=gevent --concurrency=2 --config_filepath={F.config["config_filepath"]} --running_type=native', + '', '패키지로 실행시 : -A flaskfarm.main.celery', - 'GIT 소스로 실행시 : -A main.celery (현재 작업폴더가 flaskfarm)', + 'Git 소스로 실행시 : -A main.celery', '', 'Linux는 사용자에 따라 export C_FORCE_ROOT=true 필요' ], value=arg['celery_start_command'], row='5') }} - {{ macros.setting_buttons([['celery_excute_btn', '실행 테스트']]) }} + {{ macros.setting_buttons([['celery_excute_btn', '실행 테스트'], ['celery_excute_back_btn', '실행(Background) ']]) }} {% endblock %} diff --git a/lib/tool/modal_command.py b/lib/tool/modal_command.py index d9e3d33..b9aaf77 100644 --- a/lib/tool/modal_command.py +++ b/lib/tool/modal_command.py @@ -87,12 +87,15 @@ class ToolModalCommand(object): @classmethod def process_callback(cls, mode, text): + #F.logger.warning(text) if cls.__show_modal == False: return if mode == 'end': F.socketio.emit("command_modal_add_text", "\n\n<<프로세스 종료>>", namespace='/framework', broadcast=True) F.socketio.emit("command_modal_input_disable", "", namespace='/framework', broadcast=True) - + elif mode == 'thread_end': + #F.socketio.emit("command_modal_add_text", "\n\n<<프로세스 종료>>", namespace='/framework', broadcast=True) + F.socketio.emit("command_modal_input_disable", "", namespace='/framework', broadcast=True) else: F.socketio.emit("command_modal_add_text", text, namespace='/framework', broadcast=True)