# third-party import requests import traceback import logging import threading import time import json import os from flask import ( Blueprint, request, Response, send_file, render_template, redirect, jsonify, stream_with_context, ) # gommi 공용 from framework.logger import get_logger from framework import ( app, db, scheduler, socketio, check_api, path_app_root, path_data, ) # , celery from flask_login import login_user, logout_user, current_user, login_required from framework.util import Util, SingletonClass # 로그 package_name = __name__.split(".")[0] logger = get_logger(package_name) # package from .logic import SystemLogic from .model import ModelSetting from .logic_plugin import LogicPlugin from .logic_selenium import SystemLogicSelenium from .logic_command import SystemLogicCommand from .logic_command2 import SystemLogicCommand2 from .logic_auth import SystemLogicAuth # celery 때문에 import from .logic_site import SystemLogicSite # ======================================================================== # plugin public # ======================================================================== blueprint = Blueprint( package_name, package_name, url_prefix="/%s" % package_name, template_folder="templates", ) menu = { "main": [package_name, "설정"], "sub": [ ["setting", "일반설정"], ["plugin", "플러그인"], ["tool", "Tool"], ["log", "로그"], ], "sub2": { "setting": [ ["basic", "기본"], ["auth", "인증"], ["env", "시스템"], ["notify", "알림"], ["telegram_bot", "텔레그램 봇"], ["selenium", "Selenium"], ["trans", "번역"], ["site", "Site"], ["memo", "메모"], ["terminal", "Terminal"], ], "rss": [["setting", "설정"], ["job", "작업"], ["list", "목록"]], "cache": [["setting", "설정"], ["list", "목록"]], "tool": [["crypt", "암호화"]], }, } def plugin_load(): logger.debug("plugin_load:%s", package_name) SystemLogic.plugin_load() # SystemLogicTelegramBot.plugin_load() SystemLogicSite.plugin_load() def plugin_unload(): logger.debug("plugin_load:%s", package_name) SystemLogicSelenium.plugin_unload() SystemLogicCommand.plugin_unload() SystemLogicCommand2.plugin_unload() # ============================================================ # Web menu # ============================================================ @blueprint.route("/") def normal(): return redirect("/%s/setting" % package_name) @login_required def home(): return render_template("info.html", arg=None) @blueprint.route("/", methods=["GET", "POST"]) @login_required def first_menu(sub): logger.debug("System SUB:%s", sub) arg = None if sub == "home": return render_template("%s_%s.html" % (package_name, sub), arg=None) elif sub == "setting": return redirect("/%s/%s/basic" % (package_name, sub)) elif sub == "restart": restart() return render_template( "system_restart.html", sub=sub, referer=request.headers.get("Referer"), ) elif sub == "plugin": arg = ModelSetting.to_dict() logger.debug = f"arg:: {arg}" arg["install"] = request.args.get("install", "") return render_template("system_plugin.html", arg=arg) return render_template("sample.html", title="%s - %s" % (package_name, sub)) @blueprint.route("//") @login_required def second_menu(sub, sub2): try: if sub == "setting": arg = ModelSetting.to_dict() arg["sub"] = sub2 if sub2 == "basic": arg["point"] = SystemLogic.point return render_template( "%s_%s_%s.html" % (package_name, sub, sub2), arg=arg ) elif sub2 == "auth": arg["auth_result"] = SystemLogicAuth.get_auth_status() return render_template( "%s_%s_%s.html" % (package_name, sub, sub2), arg=arg ) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) ######################################################### # For UI ######################################################### @blueprint.route("/ajax//", methods=["GET", "POST"]) @login_required def second_ajax(sub, sub2): logger.debug("System AJAX sub:%s", sub) try: if sub == "trans": from .logic_trans import SystemLogicTrans return SystemLogicTrans.process_ajax(sub2, request) elif sub == "auth": from .logic_auth import SystemLogicAuth return SystemLogicAuth.process_ajax(sub2, request) elif sub == "selenium": return SystemLogicSelenium.process_ajax(sub2, request) elif sub == "notify": return SystemLogicNotify.process_ajax(sub2, request) elif sub == "telegram_bot": return SystemLogicTelegramBot.process_ajax(sub2, request) elif sub == "env": return SystemLogicEnv.process_ajax(sub2, request) elif sub == "site": return SystemLogicSite.process_ajax(sub2, request) elif sub == "crypt": return SystemLogicToolDecrypt.process_ajax(sub2, request) elif sub == "terminal": return SystemLogicTerminal.process_ajax(sub2, request) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) @blueprint.route("/ajax/", methods=["GET", "POST"]) @login_required def ajax(sub): # logger.debug('System AJAX sub:%s', sub) try: if sub == "info": try: ret = {} ret["system"] = SystemLogic.get_info() ret["scheduler"] = scheduler.get_job_list_info() # logger.debug(ret) return jsonify(ret) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) return jsonify() elif sub == "setting_save_system": try: ret = SystemLogic.setting_save_system(request) return jsonify(ret) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) elif sub == "setting_save": ret = ModelSetting.setting_save(request) SystemLogic.setting_save_after() return jsonify(ret) elif sub == "ddns_test": try: url = request.form["ddns"] + "/version" res = requests.get(url) data = res.text # data = res.json() # logger.debug(data) return jsonify(data) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) return jsonify("fail") elif sub == "celery_test": try: # result = add_together.delay(10, 20) # print(result.wait()) # return 'Welcome to my app!' try: import framework framework.exit_code = 1 socketio.stop() except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) # os.environ['SJVA_REPEAT_TYPE'] = 'update' return jsonify() except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) elif sub == "command_run": try: command_text = request.form["command_text"] ret = SystemLogic.command_run(command_text) return jsonify(ret) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) elif sub == "get_link_list": try: link_json = SystemLogic.get_setting_value("link_json") j = json.loads(link_json) return jsonify(j) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) elif sub == "link_save": try: link_data_str = request.form["link_data"] # j = json.loads(link_data) ret = SystemLogic.link_save(link_data_str) return jsonify(ret) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) elif sub == "plugin_list": try: return jsonify(LogicPlugin.get_plugin_list()) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) elif sub == "plugin_install": try: # plugin_name = request.form['plugin_name'] plugin_git = request.form["plugin_git"] return jsonify( LogicPlugin.plugin_install_by_api( plugin_git, request.form.get("zip_url"), request.form.get("zip_filename"), ) ) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) elif sub == "plugin_uninstall": try: plugin_name = request.form["plugin_name"] return jsonify(LogicPlugin.plugin_uninstall(plugin_name)) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) elif sub == "recent_version": ret = SystemLogic.get_recent_version() ret = {"ret": ret, "version": SystemLogic.recent_version} return jsonify(ret) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) def restart(): try: try: import framework framework.exit_code = 1 app_close() except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) def shutdown(): try: try: nginx_kill = "/app/data/custom/nginx/files/kill.sh" if os.path.exists(nginx_kill): SystemLogicCommand.execute_command_return([nginx_kill]) except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) import framework framework.exit_code = 0 app_close() except Exception as exception: logger.error("Exception:%s", exception) logger.error(traceback.format_exc()) def app_close(): try: from framework.init_plugin import plugin_unload plugin_unload() socketio.stop() 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()) class InfoThread(threading.Thread): def __init__(self): super(InfoThread, self).__init__() self.stop_flag = False self.daemon = True def stop(self): self.stop_flag = True def run(self) -> None: while not self.stop_flag: ret = {} ret["system"] = SystemLogic.get_info() ret["scheduler"] = scheduler.get_job_list_info() socketio.emit( "status", ret, namespace="/system", broadcast=True ) # logger.debug('InfoThread') time.sleep(1) class InfoProcess(SingletonClass): sid_list = [] thread = None @classmethod def connect(cls, sid): logger.debug("Info connect:%s", InfoProcess.sid_list) if not InfoProcess.sid_list: InfoProcess.thread = InfoThread() InfoProcess.thread.start() InfoProcess.sid_list.append(sid) @classmethod def disconnect(cls, sid): logger.debug("Info disconnect:%s", InfoProcess.sid_list) InfoProcess.sid_list.remove(sid) if not InfoProcess.sid_list: InfoProcess.thread.stop()