This commit is contained in:
flaskfarm
2022-10-12 10:07:36 +09:00
parent 751adbbedc
commit 89fc6844ed
27 changed files with 153 additions and 2912 deletions

44
data/db/menu.yaml Normal file
View File

@@ -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: "종료"

BIN
data/db/system.db Normal file

Binary file not shown.

View File

@@ -43,7 +43,7 @@ class PluginManager:
for t in tmps: for t in tmps:
if not t.startswith('_') and os.path.isdir(os.path.join(plugin_path, t)): if not t.startswith('_') and os.path.isdir(os.path.join(plugin_path, t)):
add_plugin_list.append(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 plugins = plugins + add_plugin_list
except Exception as exception: except Exception as exception:
@@ -64,7 +64,7 @@ class PluginManager:
for t in tmps: for t in tmps:
if not t.startswith('_') and os.path.isdir(os.path.join(plugin_path, t)): if not t.startswith('_') and os.path.isdir(os.path.join(plugin_path, t)):
add_plugin_list.append(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 plugins = plugins + add_plugin_list
except Exception as exception: except Exception as exception:
F.logger.error('Exception:%s', exception) F.logger.error('Exception:%s', exception)

View File

@@ -34,10 +34,15 @@ def global_ajax(sub):
elif sub == 'is_available_edit': elif sub == 'is_available_edit':
# globalEditBtn # globalEditBtn
try: try:
import flaskcode if F.PluginManager.all_package_list['flaskcode']['loading']:
from flaskcode.setup import P as PP 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')} ret = {'ret':True, 'target':PP.ModelSetting.get('setting_open_target')}
return jsonify(ret) return jsonify(ret)
else:
return jsonify({'ret':False})
except: except:
return jsonify({'ret':False}) return jsonify({'ret':False})
elif sub == 'command_modal_hide': elif sub == 'command_modal_hide':

View File

@@ -9,13 +9,6 @@
{% endblock %} {% endblock %}
<meta name="google" value="notranslate"> <meta name="google" value="notranslate">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">-->
<!--
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
-->
<link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.ico') }}"> <link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.ico') }}">
<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet"> <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">

View File

@@ -15,7 +15,6 @@ logger = get_logger()
from .base.aes import SupportAES from .base.aes import SupportAES
from .base.discord import SupportDiscord from .base.discord import SupportDiscord
from .base.file import SupportFile from .base.file import SupportFile
from .base.process import SupportProcess
from .base.string import SupportString from .base.string import SupportString
from .base.subprocess import SupportSubprocess from .base.subprocess import SupportSubprocess
from .base.telegram import SupportTelegram from .base.telegram import SupportTelegram

View File

@@ -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)

View File

@@ -132,13 +132,16 @@ class SupportSubprocess(object):
self.start_send_callback() self.start_send_callback()
if self.process is not None: if self.process is not None:
self.process.wait() self.process.wait()
#logger.info(f"{self.command} 정상 종료") logger.info(f"{self.command} 정상 종료")
if self.stdout_queue != None:
self.stdout_queue.put('<END>')
except Exception as e: except Exception as e:
logger.error(f'Exception:{str(e)}') logger.error(f'Exception:{str(e)}')
logger.error(traceback.format_exc()) 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): def start_communicate(self):
@@ -150,8 +153,6 @@ class SupportSubprocess(object):
def rdr(): def rdr():
while True: while True:
if self.process == None:
break
buf = self.process.stdout.read(1) buf = self.process.stdout.read(1)
if buf: if buf:
_queue.put( buf ) _queue.put( buf )
@@ -178,9 +179,8 @@ class SupportSubprocess(object):
except: except:
pass pass
if r is not None: if r is not None:
if self.stdout_queue != None: #print(f"{r=}")
self.stdout_queue.put(r) self.stdout_queue.put(r)
if self.stdout_queue != None: # 사용자 중지
self.stdout_queue.put('<END>') self.stdout_queue.put('<END>')
for tgt in [rdr, clct]: for tgt in [rdr, clct]:
th = threading.Thread(target=tgt) th = threading.Thread(target=tgt)
@@ -200,10 +200,6 @@ class SupportSubprocess(object):
else: else:
if self.stdout_callback != None: if self.stdout_callback != None:
self.stdout_callback('log', line) 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 = threading.Thread(target=func, args=())
th.setDaemon(True) th.setDaemon(True)
th.start() th.start()
@@ -222,7 +218,7 @@ class SupportSubprocess(object):
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
finally: finally:
try: try:
self.stdout_queue = None #self.stdout_queue = None
self.process.kill() self.process.kill()
except: pass except: pass

View File

@@ -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

View File

@@ -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
"""

View File

@@ -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개 등록<br>회원등급:%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

View File

@@ -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('<END>')
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 == '<END>':
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)
"""

View File

@@ -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('<END>')
#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 == '<END>':
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

View File

@@ -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())

View File

@@ -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')

View File

@@ -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'] = '<br>'.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

View File

@@ -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
}
}
}
"""

View File

@@ -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'<strong>사이트 접속중입니다.</strong>'}
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

View File

@@ -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())

View File

@@ -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
'''

View File

@@ -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)}

View File

@@ -1,8 +1,10 @@
import random import random
import string import string
import time
from support import SupportDiscord, SupportFile, SupportTelegram from support import (SupportDiscord, SupportFile, SupportSubprocess,
from tool.modal_command import ToolModalCommand SupportTelegram)
from tool import ToolModalCommand
from .setup import * from .setup import *
@@ -35,7 +37,7 @@ class ModuleSetting(PluginModuleBase):
'notify.yaml': '', #직접 사용하지 않으나 저장 편의상. 'notify.yaml': '', #직접 사용하지 않으나 저장 편의상.
'command_text': '', 'command_text': '',
'celery_start_by_web': 'False', #웹 실행시 celery 실행 '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': elif page == 'celery':
arg['use_celery'] = F.config['use_celery'] arg['use_celery'] = F.config['use_celery']
arg['running_type'] = F.config['running_type'] arg['running_type'] = F.config['running_type']
return render_template(f'{__package__}_{name}_{page}.html', arg=arg) return render_template(f'{__package__}_{name}_{page}.html', arg=arg)
except Exception as e: except Exception as e:
P.logger.error(f'Exception:{str(e)}') P.logger.error(f'Exception:{str(e)}')
@@ -122,13 +123,13 @@ class ModuleSetting(PluginModuleBase):
ret['msg'] = arg1 ret['msg'] = arg1
pass pass
elif command == 'celery_execute': elif command == 'celery_execute':
tmp = arg1.replace("{F.config['config_filepath']}", F.config['config_filepath']).replace('{F.config["config_filepath"]}', F.config['config_filepath']) self.celery_execute(arg1, mode='foreground')
cmd = [ elif command == 'celery_execute_back':
['msg', f'명령 : {tmp}'], self.celery_execute(arg1, mode='background')
['msg', ''], ret['msg'] = '실행했습니다.'
tmp.split(' '), elif command == 'celery_test':
] return self.__celery_test()
ToolModalCommand.start("Celery 실행", cmd)
return jsonify(ret) return jsonify(ret)
@@ -136,9 +137,8 @@ class ModuleSetting(PluginModuleBase):
try: try:
if F.config['run_flask'] == False: if F.config['run_flask'] == False:
return return
F.logger.info(f"arg_repeat : {F.config['arg_repeat']}") if SystemModelSetting.get_bool('celery_start_by_web'):
F.logger.info(f"arg_repeat : {F.config['arg_repeat']}") self.celery_execute()
if F.config['arg_repeat'] == 0 or SystemModelSetting.get('system_start_time') == '': 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('system_start_time', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
SystemModelSetting.set('repeat', str(F.config['arg_repeat'])) SystemModelSetting.set('repeat', str(F.config['arg_repeat']))
@@ -161,15 +161,17 @@ class ModuleSetting(PluginModuleBase):
from tool import ToolNotify from tool import ToolNotify
msg = f"시스템이 시작되었습니다.\n재시작: {F.config['arg_repeat']}" msg = f"시스템이 시작되었습니다.\n재시작: {F.config['arg_repeat']}"
ToolNotify.send_message(msg, message_id='system_start') ToolNotify.send_message(msg, message_id='system_start')
except Exception as e: except Exception as e:
P.logger.error(f'Exception:{str(e)}') P.logger.error(f'Exception:{str(e)}')
P.logger.error(traceback.format_exc()) P.logger.error(traceback.format_exc())
def plugin_unload(self): def plugin_unload(self):
ToolModalCommand.process_close() ToolModalCommand.modal_close()
def setting_save_after(self, change_list): 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) F.socketio.emit("refresh", {}, namespace='/framework', broadcast=True)
elif 'notify.yaml' in change_list: elif 'notify.yaml' in change_list:
SupportFile.write_file(F.config['notify_yaml_filepath'], SystemModelSetting.get('notify.yaml')) 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) 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())

View File

@@ -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)

View File

@@ -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('/<sub>', 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('/<sub>/<sub2>')
@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/<sub>/<sub2>', 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/<sub>', 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/<sub>', 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/<sub>/<sub2>', 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)

View File

@@ -14,7 +14,6 @@ __menu = {
{'uri': 'export', 'name': 'export.sh 파일'}, {'uri': 'export', 'name': 'export.sh 파일'},
{'uri': 'celery', 'name': '비동기 작업(celery)'}, {'uri': 'celery', 'name': '비동기 작업(celery)'},
{'uri': 'notify', 'name': '알림'}, {'uri': 'notify', 'name': '알림'},
], ],
}, },
{ {

View File

@@ -16,107 +16,44 @@
{{ macros.setting_input_textarea('celery_start_command', 'celery 실행 명령', desc=['', {{ 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', '패키지로 실행시 : -A flaskfarm.main.celery',
'GIT 소스로 실행시 : -A main.celery (현재 작업폴더가 flaskfarm)', 'Git 소스로 실행시 : -A main.celery', '',
'Linux는 사용자에 따라 export C_FORCE_ROOT=true 필요' 'Linux는 사용자에 따라 export C_FORCE_ROOT=true 필요'
], ],
value=arg['celery_start_command'], row='5') }} value=arg['celery_start_command'], row='5') }}
</form> </form>
{{ macros.setting_buttons([['celery_excute_btn', '실행 테스트']]) }} {{ macros.setting_buttons([['celery_excute_btn', '실행 테스트'], ['celery_excute_back_btn', '실행(Background) ']]) }}
</div> </div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
var running_type = "{{arg['running_type']}}";
$(document).ready(function(){
console.log(running_type);
if (running_type == 'docker') {
$('#celery_start_by_web').bootstrapToggle('off');
$('#celery_start_by_web').prop('disabled', true);
}
});
$("body").on('click', '#celery_excute_btn', function(e){ $("body").on('click', '#celery_excute_btn', function(e){
e.preventDefault(); e.preventDefault();
globalSendCommand('celery_execute', $('#celery_start_command').val()); globalSendCommand('celery_execute', $('#celery_start_command').val());
}); });
$("body").on('click', '#celery_excute_back_btn', function(e){
$("body").on('click', '#shutdown_btn', function(e){
e.preventDefault(); e.preventDefault();
shutdown_confirm(); globalSendCommand('celery_execute_back', $('#celery_start_command').val());
}); });
$("body").on('click', '#celery_test_btn', function(e){ $("body").on('click', '#celery_test_btn', function(e){
e.preventDefault(); e.preventDefault();
$.ajax({ globalSendCommand('celery_test');
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> </script>

View File

@@ -87,12 +87,15 @@ class ToolModalCommand(object):
@classmethod @classmethod
def process_callback(cls, mode, text): def process_callback(cls, mode, text):
#F.logger.warning(text)
if cls.__show_modal == False: if cls.__show_modal == False:
return return
if mode == 'end': if mode == 'end':
F.socketio.emit("command_modal_add_text", "\n\n<<프로세스 종료>>", namespace='/framework', broadcast=True) F.socketio.emit("command_modal_add_text", "\n\n<<프로세스 종료>>", namespace='/framework', broadcast=True)
F.socketio.emit("command_modal_input_disable", "", 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: else:
F.socketio.emit("command_modal_add_text", text, namespace='/framework', broadcast=True) F.socketio.emit("command_modal_add_text", text, namespace='/framework', broadcast=True)