update
This commit is contained in:
@@ -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: []
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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']:
|
||||
|
||||
@@ -86,9 +86,6 @@ class MenuManager:
|
||||
|
||||
#F.logger.warning(d(cls.menu_map))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_menu_map(cls):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// 파일 선택 모달
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -19,13 +19,10 @@
|
||||
{% if 'uri' in category and category['uri'].startswith('http') %}
|
||||
<li class="nav-item"> <a class="nav-link" href="{{ category['uri']}}" target="_blank">{{category['name']}}</a></li>
|
||||
{% else %}
|
||||
|
||||
<!--{{ category }}-->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{category['name']}}</a>
|
||||
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
{% for category_child in category['list'] %}
|
||||
{% if category_child['uri'] == 'setting' %}
|
||||
<li><a class="dropdown-item" href="#" style="font-size: .850rem; font-weight:bold">{{category_child['name']}}</a>
|
||||
@@ -35,8 +32,6 @@
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
{% elif category_child['uri'] == '-' %}
|
||||
<div class="dropdown-divider"></div>
|
||||
{% elif 'uri' in category_child and category_child['uri'].startswith('http') %}
|
||||
@@ -45,6 +40,8 @@
|
||||
{% else %}
|
||||
<a class="dropdown-item" href="{{ category_child['uri'] }}" style="font-size: .850rem; font-weight:bold">{{ category_child['name'] }}</a>
|
||||
{% endif %}
|
||||
{% elif 'uri' in category_child and category_child['uri'].startswith('javascript') %}
|
||||
<a class="dropdown-item" href="{{ category_child['uri'] }}" style="font-size: .850rem; font-weight:bold">{{ category_child['name'] }}</a>
|
||||
{% else %}
|
||||
{% if category_child['uri'] == menu[0] %}
|
||||
<a class="dropdown-item active" href="/{{ category_child['uri'] }}" style="font-size: .850rem; font-weight:bold">{{ category_child['name'] }}</a>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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,
|
||||
|
||||
36
lib/system/templates/system_setting_config.html
Normal file
36
lib/system/templates/system_setting_config.html
Normal file
@@ -0,0 +1,36 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div>
|
||||
{{ 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') }}
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
$("body").on('click', '#saveBtn', function(e){
|
||||
e.preventDefault();
|
||||
globalSendCommand('config_save', $('#config').val());
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -1,144 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
|
||||
<div>
|
||||
<nav>
|
||||
{{ macros.m_tab_head_start() }}
|
||||
{{ macros.m_tab_head2('system', '시스템 변수', true) }}
|
||||
{{ macros.m_tab_head2('celery', 'celery 상태', false) }}
|
||||
{{ macros.m_tab_head_end() }}
|
||||
</nav>
|
||||
|
||||
<div class="tab-content" id="nav-tabContent">
|
||||
{{ macros.m_tab_content_start('system', true) }}
|
||||
<form id='setting' name='setting'>
|
||||
{{ macros.setting_input_textarea('export', '환경변수', desc=['',
|
||||
'도커를 재시작하거나 sjva3.sh 스크립트를 재시작해야 적용됩니다.',
|
||||
'구동 환경에 따라 사용하는 변수가 다릅니다.',
|
||||
'',
|
||||
'USE_CELERY : 멀티프로세싱 작업 사용 여부 설정. true or false',
|
||||
'CELERY_WORKER_COUNT : 작업 프로세스 개수.',
|
||||
'USE_GEVENT : 비동기 라이브러리 사용 설정. true or false. 클수록 메모리를 많이 소비하는 대신 더 원할하게 동작', '',
|
||||
'REDIS_PORT : celery에서 사용하는 redis port. 특별한 경우외에는 변경하지 마세요',
|
||||
'SJVA_PORT : 이 변수가 있는 경우 DB값을 무시하고 port로 설정',
|
||||
],
|
||||
value=arg['export'], row='10') }}
|
||||
{{ macros.setting_button([['setting_save_btn', '저장'], ['shutdown_btn', '시스템 종료']]) }}
|
||||
</form>
|
||||
</form>
|
||||
{{ macros.m_tab_content_end() }}
|
||||
|
||||
{{ macros.m_tab_content_start('celery', false) }}
|
||||
{{ macros.setting_button([['celery_test_btn', 'Celery Test'], ['worker_start_btn', '워커 재시작'], ['ps_btn', '프로세스 목록']]) }}
|
||||
|
||||
{{ macros.m_tab_content_end() }}
|
||||
</div><!--tab-content-->
|
||||
</div> <!--전체-->
|
||||
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
var package_name = "{{arg['package_name']}}";
|
||||
var sub = "{{arg['sub'] }}";
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
});
|
||||
|
||||
$("body").on('click', '#setting_save_btn', function(e){
|
||||
e.preventDefault();
|
||||
var formData = get_formdata('#setting');
|
||||
$.ajax({
|
||||
url: '/' + package_name + '/ajax/' + sub + '/setting_save',
|
||||
type: "POST",
|
||||
cache: false,
|
||||
data: formData,
|
||||
dataType: "json",
|
||||
success: function (ret) {
|
||||
if (ret) {
|
||||
$.notify('<strong>시스템 변수를 저장하였습니다.</strong>', {
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
$.notify('<strong>시스템 변수 저장에 실패하였습니다.</strong>', {
|
||||
type: 'warning'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
$("body").on('click', '#shutdown_btn', function(e){
|
||||
e.preventDefault();
|
||||
shutdown_confirm();
|
||||
});
|
||||
|
||||
$("body").on('click', '#celery_test_btn', function(e){
|
||||
e.preventDefault();
|
||||
$.ajax({
|
||||
url: '/' + package_name + '/ajax/' + sub + '/celery_test',
|
||||
type: "POST",
|
||||
cache: false,
|
||||
data: {},
|
||||
dataType: "json",
|
||||
success: function (ret) {
|
||||
if (ret.ret == 'success') {
|
||||
$.notify('<strong>'+ ret.data+'</strong>', {
|
||||
type: 'success'
|
||||
});
|
||||
} else if (ret.ret == 'timeout' || ret.ret == 'no_celery') {
|
||||
$.notify('<strong>'+ ret.data+'</strong>', {
|
||||
type: 'warning'
|
||||
});
|
||||
}
|
||||
//m_modal(ret)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$("body").on('click', '#ps_btn', function(e){
|
||||
e.preventDefault();
|
||||
$.ajax({
|
||||
url: '/' + package_name + '/ajax/' + sub + '/ps',
|
||||
type: "POST",
|
||||
cache: false,
|
||||
data: {},
|
||||
dataType: "json",
|
||||
success: function (ret) {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("body").on('click', '#worker_start_btn', function(e){
|
||||
e.preventDefault();
|
||||
$.ajax({
|
||||
url: '/' + package_name + '/ajax/' + sub + '/worker_start',
|
||||
type: "POST",
|
||||
cache: false,
|
||||
data: {},
|
||||
dataType: "json",
|
||||
success: function (ret) {
|
||||
if (ret.ret == 'success') {
|
||||
$.notify('<strong>'+ ret.data+'</strong>', {
|
||||
type: 'success'
|
||||
});
|
||||
} else if (ret.ret == 'timeout' || ret.ret == 'no_celery' || ret.ret == 'not_registered') {
|
||||
$.notify('<strong>'+ ret.data+'</strong>', {
|
||||
type: 'warning'
|
||||
});
|
||||
}
|
||||
//m_modal(ret)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
31
lib/system/templates/system_setting_export.html
Normal file
31
lib/system/templates/system_setting_export.html
Normal file
@@ -0,0 +1,31 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div>
|
||||
{{ 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') }}
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
$("body").on('click', '#saveBtn', function(e){
|
||||
e.preventDefault();
|
||||
globalSendCommand('export_save', $('#export').val());
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
27
lib/system/templates/system_setting_menu.html
Normal file
27
lib/system/templates/system_setting_menu.html
Normal file
@@ -0,0 +1,27 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div>
|
||||
{{ 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') }}
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
$("body").on('click', '#saveBtn', function(e){
|
||||
e.preventDefault();
|
||||
globalSendCommand('menu_save', $('#menu').val());
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -1,10 +1,10 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
|
||||
<div>
|
||||
{{ macros.m_button_group([['globalSettingSaveBtn', '설정 저장']])}}
|
||||
{{ macros.m_row_start('5') }}
|
||||
{{ macros.m_row_end() }}
|
||||
{{ macros.m_hr() }}
|
||||
<nav>
|
||||
{{ macros.m_tab_head_start() }}
|
||||
{{ macros.m_tab_head2('basic', 'Basic', true) }}
|
||||
@@ -33,7 +33,7 @@
|
||||
{{ macros.m_tab_content_start('advanced', false) }}
|
||||
{{ macros.setting_checkbox('notify_advaned_use', '사용', value=arg['notify_advaned_use'], desc=['충분히 내용 숙지하고 사용하세요.', '사용시 기본설정은 무시됩니다.']) }}
|
||||
<div id="notify_advaned_use_div" class="collapse">
|
||||
{{ macros.setting_input_textarea('notify_advaned_policy', '정책', value=arg['notify_advaned_policy'], row='30') }}
|
||||
{{ macros.setting_input_textarea('_notify_advaned_policy', '정책', value=arg['notify_advaned_policy'], row='30') }}
|
||||
{{ macros.setting_input_text_and_buttons('tmp_text_advanced', 'Test', [['tmp_advanced_test_btn', '전송']], value='테스트 메시지입니다.', col='9', desc=['메시지 ID = 형식', '형식의 구분자 |', '텔레그램 : bot_token,chat_id | 디스코드 : 웹훅 URL', '예) DEFAULT = 794150118:AAEAAAAAAAAAAAAAAA,186485141|https://discordapp.com/api/webhooks/626295849....', '모든 알림을 텔레그램과 디스코드에 보냄']) }}
|
||||
{{ macros.setting_input_text('tmp_message_id', 'Test Message ID', value='DEFAULT') }}
|
||||
</div>
|
||||
|
||||
125
lib/tool/notify.py
Normal file
125
lib/tool/notify.py
Normal file
@@ -0,0 +1,125 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#########################################################
|
||||
|
||||
import os
|
||||
import traceback
|
||||
|
||||
from discord_webhook import DiscordEmbed, DiscordWebhook
|
||||
from framework import F
|
||||
from telepot2 import Bot, glance
|
||||
from telepot2.loop import MessageLoop
|
||||
|
||||
from . import logger
|
||||
|
||||
|
||||
class ToolNotify(object):
|
||||
|
||||
@classmethod
|
||||
def send_message(cls, text, message_id=None, image_url=None):
|
||||
if F.SystemModelSetting.get_bool('notify_advaned_use'):
|
||||
return cls.send_advanced_message(text, image_url=image_url, message_id=message_id)
|
||||
else:
|
||||
if F.SystemModelSetting.get_bool('notify_telegram_use'):
|
||||
cls.send_telegram_message(text, image_url=image_url, bot_token=F.SystemModelSetting.get('notify_telegram_token'), chat_id=F.SystemModelSetting.get('notify_telegram_chat_id'))
|
||||
if F.SystemModelSetting.get_bool('notify_discord_use'):
|
||||
cls.send_discord_message(text, image_url=image_url, webhook_url=F.SystemModelSetting.get('notify_discord_webhook'))
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def send_advanced_message(cls, text, image_url=None, policy=None, message_id=None):
|
||||
from system.model import ModelSetting as SystemModelSetting
|
||||
try:
|
||||
if policy is None:
|
||||
policy = SystemModelSetting.get('notify_advaned_policy')
|
||||
|
||||
if message_id is None:
|
||||
message_id = 'DEFAULT'
|
||||
|
||||
policy_list = cls._make_policy_dict(policy)
|
||||
#logger.debug(policy_list)
|
||||
#logger.debug(message_id)
|
||||
if message_id.strip() not in policy_list:
|
||||
message_id = 'DEFAULT'
|
||||
|
||||
for tmp in policy_list[message_id.strip()]:
|
||||
if tmp.startswith('http'):
|
||||
cls.send_discord_message(text, image_url=image_url, webhook_url=tmp)
|
||||
elif tmp.find(',') != -1:
|
||||
tmp2 = tmp.split(',')
|
||||
cls.send_telegram_message(text, image_url=image_url, bot_token=tmp2[0], chat_id=tmp2[1])
|
||||
return True
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
logger.error(traceback.format_exc())
|
||||
#logger.debug('Chatid:%s', chat_id)
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def _make_policy_dict(cls, policy):
|
||||
try:
|
||||
ret = {}
|
||||
for t in policy.split('\n'):
|
||||
t = t.strip()
|
||||
if t == '' or t.startswith('#'):
|
||||
continue
|
||||
else:
|
||||
tmp2 = t.split('=')
|
||||
if len(tmp2) != 2:
|
||||
continue
|
||||
ret[tmp2[0].strip()] = [x.strip() for x in tmp2[1].split('|')]
|
||||
return ret
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def send_discord_message(cls, text, image_url=None, webhook_url=None):
|
||||
from system.model import ModelSetting as SystemModelSetting
|
||||
try:
|
||||
if webhook_url is None:
|
||||
webhook_url = SystemModelSetting.get('notify_discord_webhook')
|
||||
|
||||
webhook = DiscordWebhook(url=webhook_url, content=text)
|
||||
if image_url is not None:
|
||||
embed = DiscordEmbed()
|
||||
embed.set_timestamp()
|
||||
embed.set_image(url=image_url)
|
||||
webhook.add_embed(embed)
|
||||
response = webhook.execute()
|
||||
#discord = response.json()
|
||||
#logger.debug(discord)
|
||||
return True
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
logger.error(traceback.format_exc())
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def send_telegram_message(cls, text, bot_token=None, chat_id=None, image_url=None, disable_notification=None):
|
||||
from system.model import ModelSetting as SystemModelSetting
|
||||
try:
|
||||
if bot_token is None:
|
||||
bot_token = SystemModelSetting.get('notify_telegram_token')
|
||||
|
||||
if chat_id is None:
|
||||
chat_id = SystemModelSetting.get('notify_telegram_chat_id')
|
||||
|
||||
if disable_notification is None:
|
||||
disable_notification = SystemModelSetting.get_bool('notify_telegram_disable_notification')
|
||||
|
||||
bot = Bot(bot_token)
|
||||
if image_url is not None:
|
||||
#bot.sendPhoto(chat_id, text, caption=caption, disable_notification=disable_notification)
|
||||
bot.sendPhoto(chat_id, image_url, disable_notification=disable_notification)
|
||||
bot.sendMessage(chat_id, text, disable_web_page_preview=True, disable_notification=disable_notification)
|
||||
#elif mime == 'video':
|
||||
# bot.sendVideo(chat_id, text, disable_notification=disable_notification)
|
||||
return True
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
logger.error(traceback.format_exc())
|
||||
logger.debug('Chatid:%s', chat_id)
|
||||
return False
|
||||
|
||||
4
main.py
4
main.py
@@ -12,7 +12,9 @@ sys.path.insert(1, os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib
|
||||
|
||||
try:
|
||||
from framework import frame
|
||||
if __name__ in ['__main__', 'flaskfarm.main']:
|
||||
|
||||
# flaskfarm.main : 패키지로 실행. 패키지로 celry 실행 체크
|
||||
if __name__ in ['__main__', 'flaskfarm.main'] and sys.argv[0].endswith('celery') == False:
|
||||
frame.start()
|
||||
else:
|
||||
app = frame.app
|
||||
|
||||
Reference in New Issue
Block a user