diff --git a/files/config.yaml.docker b/files/config.yaml.docker index ff6e64f..496b9a4 100644 --- a/files/config.yaml.docker +++ b/files/config.yaml.docker @@ -1,14 +1,11 @@ path_data: "/data" -use_gevent: true -use_celery: true -redis_port: 46379 -port: 9999 -debug: false -use_reloader: false -plugin_update: true - - +#use_gevent: true +#use_celery: true +#debug: false +#redis_port: 46379 +#port: 9999 +#plugin_update: false #running_type: "docker" #plugin_loading_only_devpath: true #plugin_loading_list: [] diff --git a/files/config.yaml.template b/files/config.yaml.template index 64d3295..66b8501 100644 --- a/files/config.yaml.template +++ b/files/config.yaml.template @@ -6,39 +6,36 @@ path_data: "." #path_data: "/mnt/c/work/FlaskFarm/working" # gevent 사용여부 -# 거의 항상 true로 사용. # 플러그인 개발이나 termux 환경에서의 실행 같이 특수한 경우에만 false로 사용. # 실행환경에 gevent 관련 패키지가 설치되어 있지 않는다면 값과 상관 없이 false로 동작. -# false인 경우 -use_gevent: true +#use_gevent: true # celery 사용 여부 -use_celery: true +#use_celery: true # redis port # celery를 사용하는 경우 사용하는 redis 포트 -redis_port: 6379 +# 환경변수 REDIS_PORT 값이 있는 경우 무시됨. +#redis_port: 6379 # 포트 # 생략시 DB 값을 사용. -port: 9999 +#port: 9999 # 소스 수정시 재로딩 -# 두번 로딩되는 것을 감안하여 코딩해야 함. 기본실행, subporcess 실행 -debug: false - -use_reloader: false +# 두번 로딩되는 것을 감안하여 코딩해야 함. +#debug: false # 플러그인 업데이트 여부 # - true인 경우 로딩시 플러그인을 업데이트 함. -# 데이터폴더/plugins 폴더 안에 플러그인 만을 대상으로 함. +# /data/plugins 폴더에 있는 플러그인 만을 대상으로 함. # - debug 값이 true인 경우에는 항상 false -plugin_update: true +#plugin_update: true # running_type -# termux, entware 인 경우 입력 함. (이외 사용하는 값 native, docker) +# termux, entware 인 경우 입력 함. #running_type: "native" diff --git a/files/menu.yaml.template b/files/menu.yaml.template index ebf2fb4..a8ac393 100644 --- a/files/menu.yaml.template +++ b/files/menu.yaml.template @@ -1,40 +1,29 @@ # 카테고리 - # uri 가 plugin인 경우 name 값은 대체 -- name: "토렌트" - list: - - uri: "rss2" +#- name: "토렌트" +# list: +# - uri: "rss" -- name: "즐겨찾기" - list: - - uri: "number_baseball" +#- name: "기본 기능" +# list: +# - uri: "terminal" # - uri: "command" # - uri: "flaskfilemanager" # - uri: "flaskcode" - -- name: "기본 기능" - list: - - uri: "terminal" - - uri: "command" - - uri: "flaskfilemanager" - - uri: "flaskcode" - - uri: "number_baseball" +# - uri: "number_baseball" -- name: "링크" - list: - - uri: "https://app.plex.tv" - name: "Plex" - target: "_self" - - uri: "https://app.plex.tv" - name: "Netflix" +#- name: "링크" +# list: +# - uri: "https://app.plex.tv" +# name: "Plex" +# target: "_self" +# - uri: "https://www.netflix.com" +# name: "Netflix" -- name: "Plex" - uri: "https://app.plex.tv" - - name: "시스템" list: - uri: "system" diff --git a/lib/framework/init_main.py b/lib/framework/init_main.py index d2250f8..0bacd2d 100644 --- a/lib/framework/init_main.py +++ b/lib/framework/init_main.py @@ -97,13 +97,13 @@ class Framework: #if frame.config['use_celery'] == False or platform.system() == 'Windows': if self.config['use_celery'] == False: raise Exception('no celery') - try: - redis_port = os.environ['REDIS_PORT'] - except: - try: - redis_port = self.config['redis_port'] - except: - redis_port = '6379' + + redis_port = os.environ.get('REDIS_PORT', None) + if redis_port == None: + redis_port = self.config.get('redis_port', None) + if redis_port == None: + redis_port = '6379' + self.app.config['CELERY_BROKER_URL'] = 'redis://localhost:%s/0' % redis_port self.app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:%s/0' % redis_port @@ -183,7 +183,7 @@ class Framework: if self.config['run_flask']: if self.config.get('port') == None: - self.config['port'] = SP.SystemModelSetting.get_int('port') + self.config['port'] = self.SystemModelSetting.get_int('port') from . import init_route, log_viewer @@ -216,9 +216,12 @@ class Framework: self.config['path_working'] = os.getcwd() if os.environ.get('RUNNING_TYPE') == 'docker': self.config['running_type'] = 'docker' + self.config['export_filepath'] = os.path.join(self.config['path_app'], 'export.sh') + self.config['exist_export'] = os.path.exists(self.config['export_filepath']) self.__process_args() self.__load_config() self.__init_define() + self.config['menu_yaml_filepath'] = os.path.join(self.config['path_data'], 'db', 'menu.yaml') elif mode == "flask": self.app.secret_key = os.urandom(24) #self.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data/db/system.db?check_same_thread=False' @@ -298,7 +301,22 @@ class Framework: # 예외적으로 현재폴더가 app일 경우 지저분해지는 것을 방지하기 위해 data 로 지정 if self.config['path_data'] == self.config['path_working']: self.config['path_data'] = os.path.join(self.config['path_working'], 'data') - self.path_data = self.config['path_data'] + self.path_data = self.config['path_data'] + + if self.config.get('use_gevent') == None: + self.config['use_gevent'] = True + if self.config.get('use_celery') == None: + self.config['use_celery'] = True + if self.config.get('debug') == None: + self.config['debug'] = False + if self.config.get('plugin_update') == None: + self.config['plugin_update'] = True + if self.config.get('plugin_loading_only_devpath') == None: + self.config['plugin_loading_only_devpath'] = False + if self.config.get('plugin_loading_list') == None: + self.config['plugin_loading_list'] = [] + if self.config.get('plugin_except_list') == None: + self.config['plugin_except_list'] = [] @@ -399,7 +417,7 @@ class Framework: for i in range(10): try: #self.logger.debug(d(self.config)) - self.socketio.run(self.app, host=host, port=self.config['port'], debug=self.config['debug'], use_reloader=self.config['use_reloader']) + self.socketio.run(self.app, host=host, port=self.config['port'], debug=self.config['debug'], use_reloader=self.config['debug']) self.logger.warning(f"EXIT CODE : {self.__exit_code}") # 2021-05-18 if self.config['running_type'] in ['termux', 'entware']: diff --git a/lib/framework/init_menu.py b/lib/framework/init_menu.py index 3861572..3557133 100644 --- a/lib/framework/init_menu.py +++ b/lib/framework/init_menu.py @@ -86,9 +86,6 @@ class MenuManager: #F.logger.warning(d(cls.menu_map)) - - - @classmethod def get_menu_map(cls): diff --git a/lib/framework/init_plugin.py b/lib/framework/init_plugin.py index 91dc80f..581eccd 100644 --- a/lib/framework/init_plugin.py +++ b/lib/framework/init_plugin.py @@ -63,7 +63,7 @@ class PluginManager: # plugin_loading_list try: plugin_loading_list = F.config.get('plugin_loading_list', None) - if plugin_loading_list != None and type(plugin_loading_list) == type([]): + if plugin_loading_list != None and (type(plugin_loading_list) == type([]) and len(plugin_loading_list)) > 0: new_plugins = [] for _ in plugins: if _ in plugin_loading_list: @@ -76,7 +76,7 @@ class PluginManager: # plugin_except_list try: plugin_except_list = F.config.get('plugin_except_list', None) - if plugin_except_list != None and type(plugin_except_list) == type([]): + if plugin_except_list != None and (type(plugin_except_list) == type([]) and len(plugin_except_list)) > 0: new_plugins = [] for _ in plugins: if _ not in plugin_except_list: diff --git a/lib/framework/static/js/ff_global1.js b/lib/framework/static/js/ff_global1.js index cbbe54f..20ef948 100644 --- a/lib/framework/static/js/ff_global1.js +++ b/lib/framework/static/js/ff_global1.js @@ -146,6 +146,13 @@ function globalSendCommand(command, arg1, arg2, arg3, modal_title, callback) { }); } +function shutdown_confirm() { + $("#confirm_title").html("종료 확인"); + $("#confirm_body").html("종료 하시겠습니까?"); + $('#confirm_button').attr('onclick', 'window.location.href = "/system/shutdown";'); + $("#confirm_modal").modal(); +} + /////////////////////////////////////// // 파일 선택 모달 diff --git a/lib/framework/static/js/sjva_global1.js b/lib/framework/static/js/sjva_global1.js index 1998382..15d752d 100644 --- a/lib/framework/static/js/sjva_global1.js +++ b/lib/framework/static/js/sjva_global1.js @@ -166,12 +166,7 @@ function global_relay_test(remote) { -function shutdown_confirm() { - document.getElementById("confirm_title").innerHTML = "종료 확인"; - document.getElementById("confirm_body").innerHTML = "종료 하시겠습니까?"; - $('#confirm_button').attr('onclick', 'window.location.href = "/system/shutdown";'); - $("#confirm_modal").modal(); -} + $("#video_modal").on('hidden.bs.modal', function () { document.getElementById("video_modal_video").pause(); diff --git a/lib/framework/templates/macro_menu.html b/lib/framework/templates/macro_menu.html index c458d10..60fd0a7 100644 --- a/lib/framework/templates/macro_menu.html +++ b/lib/framework/templates/macro_menu.html @@ -19,13 +19,10 @@ {% if 'uri' in category and category['uri'].startswith('http') %} {% else %} - - - {% elif category_child['uri'] == '-' %} {% elif 'uri' in category_child and category_child['uri'].startswith('http') %} @@ -45,6 +40,8 @@ {% else %} {{ category_child['name'] }} {% endif %} + {% elif 'uri' in category_child and category_child['uri'].startswith('javascript') %} + {{ category_child['name'] }} {% else %} {% if category_child['uri'] == menu[0] %} {{ category_child['name'] }} diff --git a/lib/system/logic_plugin.py b/lib/system/logic_plugin.py index a2c9c00..664f2a6 100644 --- a/lib/system/logic_plugin.py +++ b/lib/system/logic_plugin.py @@ -1,26 +1,25 @@ # -*- coding: utf-8 -*- ######################################################### # python -import os -import traceback -import logging import json -import zipfile -import time +import logging +import os import platform +import time +import traceback +import zipfile + # third-party import requests - - # sjva 공용 -from framework import frame, app, path_data, logger +from framework import app, frame, logger, path_data from framework.util import Util from support.base.process import SupportProcess -# 패키지 -from .model import ModelSetting import system +# 패키지 +from .model import ModelSetting class LogicPlugin(object): @@ -153,7 +152,7 @@ class LogicPlugin(object): return if frame.config['debug'] == True: return - if frame.config['plugin_update'] != True: + if frame.config.get('plugin_update', True) != True: return custom_path = os.path.join(path_data, 'plugins') @@ -213,6 +212,7 @@ class LogicPlugin(object): 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) diff --git a/lib/system/mod_setting.py b/lib/system/mod_setting.py index fab9792..f15aa3f 100644 --- a/lib/system/mod_setting.py +++ b/lib/system/mod_setting.py @@ -1,6 +1,8 @@ import random import string +from support.base.file import SupportFile + from .setup import * name = 'setting' @@ -16,14 +18,19 @@ class ModuleSetting(PluginModuleBase): 'web_title': 'Home', 'use_apikey': 'False', 'apikey': ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10)), - f'restart_interval': f'{random.randint(0,59)} {random.randint(1,23)} * * *', - 'theme' : 'Cerulean', 'log_level' : '20', 'plugin_dev_path': os.path.join(F.config['path_data'], 'dev'), - 'system_start_time': '', + # 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', } def __init__(self, P): @@ -33,6 +40,18 @@ class ModuleSetting(PluginModuleBase): def process_menu(self, page, req): arg = P.ModelSetting.to_dict() try: + if page == 'config': + arg['config.yaml'] = SupportFile.read_file(F.config['config_filepath']) + arg['config_filepath'] = F.config['config_filepath'] + elif page == 'export': + arg['export_filepath'] = F.config['export_filepath'] + if F.config['exist_export']: + arg['export.sh'] = SupportFile.read_file(export) + else: + arg['export.sh'] = "export.sh 파일이 없습니다." + elif page == 'menu': + arg['menu_yaml_filepath'] = F.config['menu_yaml_filepath'] + arg['menu.yaml'] = SupportFile.read_file(arg['menu_yaml_filepath']) return render_template(f'{__package__}_{name}_{page}.html', arg=arg) except Exception as e: P.logger.error(f'Exception:{str(e)}') @@ -40,8 +59,31 @@ class ModuleSetting(PluginModuleBase): return render_template('sample.html', title=f"{__package__}/{name}/{page}") def process_command(self, command, arg1, arg2, arg3, req): + ret = {'ret':'success'} if command == 'apikey_generate': return jsonify(''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))) + elif command == 'config_save': + SupportFile.write_file(F.config['config_filepath'], arg1 ) + ret['msg'] = '저장하였습니다.' + elif command == 'export_save': + if F.config['exist_export']: + SupportFile.write_file(F.config['export_filepath'], arg1 ) + ret['msg'] = '저장하였습니다.' + else: + ret['ret'] = 'warning' + ret['msg'] = 'export.sh 파일이 없습니다.' + elif command == 'menu_save': + SupportFile.write_file(F.config['menu_yaml_filepath'], arg1 ) + ret['msg'] = '저장하였습니다.' + from framework.init_menu import MenuManager + MenuManager.init_menu() + F.socketio.emit("refresh", {}, namespace='/framework', broadcast=True) + elif command == 'notify_test': + if arg1 == 'telegram': + pass + + return jsonify(ret) + def plugin_load(self): @@ -56,6 +98,7 @@ class ModuleSetting(PluginModuleBase): self.__set_restart_scheduler() self.__set_scheduler_check_scheduler() F.get_recent_version() + except Exception as e: P.logger.error(f'Exception:{str(e)}') P.logger.error(traceback.format_exc()) diff --git a/lib/system/setup.py b/lib/system/setup.py index ac322a7..0d94bc3 100644 --- a/lib/system/setup.py +++ b/lib/system/setup.py @@ -9,23 +9,23 @@ __menu = { {'uri': 'basic', 'name': '기본'}, {'uri': 'auth', 'name': '인증'}, {'uri': 'web', 'name': '웹'}, - {'uri': 'env', 'name': '시스템'}, - {'uri': 'menu', 'name': '메뉴'}, + {'uri': 'menu', 'name': '메뉴 구성'}, + {'uri': 'config', 'name': 'config.yaml 파일'}, + {'uri': 'export', 'name': 'export.sh 파일'}, {'uri': 'notify', 'name': '알림'}, - {'uri': 'crypt', 'name': '암호화'}, + ], }, + {'uri': 'plugin', 'name': '플러그인'}, { - 'uri': 'plugin', - 'name': '플러그인' - }, - { - 'uri': 'python', - 'name': 'Python' - }, - { - 'uri': 'db', - 'name': 'DB' + 'uri': 'tool', + 'name': '시스템 툴', + 'list': [ + {'uri': 'celery', 'name': 'celery 테스트'}, + {'uri': 'python', 'name': 'Python'}, + {'uri': 'db', 'name': 'DB'}, + {'uri': 'crypt', 'name': '암호화'}, + ] }, { 'uri': 'log', @@ -34,7 +34,20 @@ __menu = { ] } - + +import os + +from framework import F + +export = os.path.join(F.config['path_app'], 'export.sh') +if os.path.exists(export) == False: + for mod in __menu['list']: + if mod['uri'] == 'setting': + del mod['list'][5] + + + + setting = { 'filepath' : __file__, 'use_db': True, diff --git a/lib/system/templates/system_setting_config.html b/lib/system/templates/system_setting_config.html new file mode 100644 index 0000000..e9a0f11 --- /dev/null +++ b/lib/system/templates/system_setting_config.html @@ -0,0 +1,36 @@ +{% extends "base.html" %} +{% block content %} +
+ {{ macros.m_button_group([['saveBtn', '파일 저장']])}} + {{ macros.m_row_start('5') }} + {{ macros.m_row_end() }} + {{ macros.m_hr() }} + + {{ macros.info_text_and_buttons('config_filepath', '파일 위치', [['globalEditBtn', '편집기에서 열기', [('file',arg['config_filepath'])]]], value=arg['config_filepath']) }} + {{ macros.setting_input_textarea('config', 'config.yaml', desc=['', + 'App을 재시작 해야 적용됩니다.', + '', + 'path_data : 필수. 데이터 폴더 경로. 윈도우의 경우 폴더 구분 기호 \ 를 두개 사용', + 'use_gevent : 생략시 true', + 'use_celery : 생략시 true', + 'redis_port : 생략시 6379', + 'port : 생략시 설정에 있는 DB port 사용. 설정시 DB 값보다 우선 사용', + 'debug : 생략시 false. true인 경우 소스 수정시 재로딩', + 'plugin_update : 생략시 true. 환경변수 UPDATE_STOP, PLUGIN_UPDATE_FROM_PYTHON 값이 설정된 경우에도 적용', + 'running_type : termux, entware인 경우에만 입력', + 'plugin_loading_only_devpath : true인 경우 플러그인 개발 폴더에 있는 것들만 로딩', + 'plugin_loading_list : 생략시 적용 안함. 로딩할 모듈 패키지명 리스트', + 'plugin_except_list : 생략시 적용 안함. 로딩 제외할 모듈 패키지명 리스트', + ], + value=arg['config.yaml'], row='20') }} +
+ + +{% endblock %} diff --git a/lib/system/templates/system_setting_env.html b/lib/system/templates/system_setting_env.html deleted file mode 100644 index b6cc2cf..0000000 --- a/lib/system/templates/system_setting_env.html +++ /dev/null @@ -1,144 +0,0 @@ -{% extends "base.html" %} -{% block content %} - -
- - - -
- - - - - -{% endblock %} diff --git a/lib/system/templates/system_setting_export.html b/lib/system/templates/system_setting_export.html new file mode 100644 index 0000000..71768a0 --- /dev/null +++ b/lib/system/templates/system_setting_export.html @@ -0,0 +1,31 @@ +{% extends "base.html" %} +{% block content %} +
+ {{ macros.m_button_group([['saveBtn', '파일 저장']])}} + {{ macros.m_row_start('5') }} + {{ macros.m_row_end() }} + {{ macros.m_hr() }} + + {{ macros.info_text_and_buttons('export_filepath', '파일 위치', [['globalEditBtn', '편집기에서 열기', [('file',arg['export_filepath'])]]], value=arg['export_filepath']) }} + {{ macros.setting_input_textarea('export', 'export.sh', desc=['', + '도커를 재시작하거나 flaskfarm.sh 스크립트를 재시작해야 적용됩니다.', + '구동 환경에 따라 사용하는 변수가 다릅니다.', + '', + 'REDIS_PORT : celery에서 사용하는 redis port.', + 'CELERY_WORKER_COUNT : celery 작업 프로세스 개수.', + 'UPDATE_STOP : true인 경우 앱과 플러그인을 업데이트 하지 않음', + 'DOCKER_NONSTOP : true인 경우 App이 종료되어서 도커가 중단되지 않음. 개발시 사용', + 'PLUGIN_UPDATE_FROM_PYTHON : false인 경우 shell에서 업데이트 실행. true인 경우 앱에서 업데이트 실행.', + ], + value=arg['export.sh'], row='20') }} +
+ + +{% endblock %} diff --git a/lib/system/templates/system_setting_menu.html b/lib/system/templates/system_setting_menu.html new file mode 100644 index 0000000..8109e7a --- /dev/null +++ b/lib/system/templates/system_setting_menu.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} +{% block content %} +
+ {{ macros.m_button_group([['saveBtn', '파일 저장']])}} + {{ macros.m_row_start('5') }} + {{ macros.m_row_end() }} + {{ macros.m_hr() }} + + {{ macros.info_text_and_buttons('menu_yaml_filepath', '파일 위치', [['globalEditBtn', '편집기에서 열기', [('file',arg['menu_yaml_filepath'])]]], value=arg['menu_yaml_filepath']) }} + {{ macros.setting_input_textarea('menu', 'menu.yaml', desc=['', + 'uri 값', + '플러그인 : 패키지 이름', + '바로가기 : http로 시작하는 링크. 기본값은 새창에서 열기. target: "__self" 값이 있는 경우 기본창', + '구분선 : -', + ], + value=arg['menu.yaml'], row='30') }} +
+ + +{% endblock %} diff --git a/lib/system/templates/system_setting_notify.html b/lib/system/templates/system_setting_notify.html index 4821c3f..168f61d 100644 --- a/lib/system/templates/system_setting_notify.html +++ b/lib/system/templates/system_setting_notify.html @@ -1,10 +1,10 @@ {% extends "base.html" %} {% block content %} -
{{ macros.m_button_group([['globalSettingSaveBtn', '설정 저장']])}} {{ macros.m_row_start('5') }} {{ macros.m_row_end() }} + {{ macros.m_hr() }}