diff --git a/plugins/memcached/bak/index_2022_6_18.py b/plugins/memcached/bak/index_2022_6_18.py
deleted file mode 100755
index 83e7093de..000000000
--- a/plugins/memcached/bak/index_2022_6_18.py
+++ /dev/null
@@ -1,242 +0,0 @@
-# coding:utf-8
-
-import sys
-import io
-import os
-import time
-import re
-
-sys.path.append(os.getcwd() + "/class/core")
-import mw
-
-app_debug = False
-if mw.isAppleSystem():
- app_debug = True
-
-
-def getPluginName():
- return 'memcached'
-
-
-def getPluginDir():
- return mw.getPluginDir() + '/' + getPluginName()
-
-
-def getServerDir():
- return mw.getServerDir() + '/' + getPluginName()
-
-
-def getInitDFile():
- if app_debug:
- return '/tmp/' + getPluginName()
- return '/etc/init.d/' + getPluginName()
-
-
-def getConf():
- path = getServerDir() + "/init.d/memcached"
- return path
-
-
-def getConfTpl():
- path = getPluginDir() + "/init.d/memcached.tpl"
- return path
-
-
-def getMemPort():
- path = getConf()
- content = mw.readFile(path)
- rep = 'PORT\s*=\s*(\d*)'
- tmp = re.search(rep, content)
- return tmp.groups()[0]
-
-
-def getArgs():
- args = sys.argv[2:]
- tmp = {}
- args_len = len(args)
-
- if args_len == 1:
- t = args[0].strip('{').strip('}')
- t = t.split(':')
- tmp[t[0]] = t[1]
- elif args_len > 1:
- for i in range(len(args)):
- t = args[i].split(':')
- tmp[t[0]] = t[1]
-
- return tmp
-
-
-def status():
- data = mw.execShell(
- "ps -ef|grep " + getPluginName() + " |grep -v grep | grep -v python | awk '{print $2}'")
- if data[0] == '':
- return 'stop'
- return 'start'
-
-
-def initDreplace():
-
- file_tpl = getConfTpl()
- service_path = mw.getServerDir()
-
- initD_path = getServerDir() + '/init.d'
- if not os.path.exists(initD_path):
- os.mkdir(initD_path)
- file_bin = initD_path + '/memcached'
-
- if not os.path.exists(file_bin):
- content = mw.readFile(file_tpl)
- content = content.replace('{$SERVER_PATH}', service_path)
- mw.writeFile(file_bin, content)
- mw.execShell('chmod +x ' + file_bin)
-
- return file_bin
-
-
-def memOp(method):
- file = initDreplace()
- data = mw.execShell(file + ' ' + method)
- if data[1] == '':
- return 'ok'
- return data[1]
-
-
-def start():
- return memOp('start')
-
-
-def stop():
- return memOp('stop')
-
-
-def restart():
- return memOp('restart')
-
-
-def reload():
- return memOp('reload')
-
-
-def runInfo():
- # 获取memcached状态
- import telnetlib
- import re
- port = getMemPort()
- try:
- tn = telnetlib.Telnet('127.0.0.1', int(port))
- tn.write(b"stats\n")
- tn.write(b"quit\n")
- data = tn.read_all()
- if type(data) == bytes:
- data = data.decode('utf-8')
- data = data.replace('STAT', '').replace('END', '').split("\n")
- result = {}
- res = ['cmd_get', 'get_hits', 'get_misses', 'limit_maxbytes', 'curr_items', 'bytes',
- 'evictions', 'limit_maxbytes', 'bytes_written', 'bytes_read', 'curr_connections']
- for d in data:
- if len(d) < 3:
- continue
- t = d.split()
- if not t[0] in res:
- continue
- result[t[0]] = int(t[1])
- result['hit'] = 1
- if result['get_hits'] > 0 and result['cmd_get'] > 0:
- result['hit'] = float(result['get_hits']) / \
- float(result['cmd_get']) * 100
-
- conf = mw.readFile(getConf())
- result['bind'] = re.search('IP=(.+)', conf).groups()[0]
- result['port'] = int(re.search('PORT=(\d+)', conf).groups()[0])
- result['maxconn'] = int(re.search('MAXCONN=(\d+)', conf).groups()[0])
- result['cachesize'] = int(
- re.search('CACHESIZE=(\d+)', conf).groups()[0])
- return mw.getJson(result)
- except Exception as e:
- return mw.getJson({})
-
-
-def saveConf():
- # 设置memcached缓存大小
- import re
- confFile = getConf()
- # print confFile
- try:
- args = getArgs()
- content = mw.readFile(confFile)
- content = re.sub('IP=.+', 'IP=' + args['ip'], content)
- content = re.sub('PORT=\d+', 'PORT=' + args['port'], content)
- content = re.sub('MAXCONN=\d+', 'MAXCONN=' + args['maxconn'], content)
- content = re.sub('CACHESIZE=\d+', 'CACHESIZE=' +
- args['cachesize'], content)
- mw.writeFile(confFile, content)
- restart()
- return 'save ok'
- except Exception as e:
- pass
- return 'fail'
-
-
-def initdStatus():
- if not app_debug:
- if mw.isAppleSystem():
- return "Apple Computer does not support"
- initd_bin = getInitDFile()
- if os.path.exists(initd_bin):
- return 'ok'
- return 'fail'
-
-
-def initdInstall():
- import shutil
- if not app_debug:
- if mw.isAppleSystem():
- return "Apple Computer does not support"
-
- mem_bin = initDreplace()
- initd_bin = getInitDFile()
- shutil.copyfile(mem_bin, initd_bin)
- mw.execShell('chmod +x ' + initd_bin)
- mw.execShell('chkconfig --add ' + getPluginName())
- return 'ok'
-
-
-def initdUinstall():
- if not app_debug:
- if mw.isAppleSystem():
- return "Apple Computer does not support"
-
- mw.execShell('chkconfig --del ' + getPluginName())
- initd_bin = getInitDFile()
- os.remove(initd_bin)
- return 'ok'
-
-if __name__ == "__main__":
- func = sys.argv[1]
- if func == 'status':
- print(status())
- elif func == 'start':
- print(start())
- elif func == 'stop':
- print(stop())
- elif func == 'restart':
- print(restart())
- elif func == 'reload':
- print(reload())
- elif func == 'initd_status':
- print(initdStatus())
- elif func == 'initd_install':
- print(initdInstall())
- elif func == 'initd_uninstall':
- print(initdUinstall())
- elif func == 'run_info':
- print(runInfo())
- elif func == 'conf':
- print(getConf())
- elif func == 'conf_tpl':
- print(getConfTpl())
- elif func == 'save_conf':
- print(saveConf())
- else:
- print('fail')
diff --git a/plugins/webhook/ico.png b/plugins/webhook/ico.png
new file mode 100644
index 000000000..633088a7e
Binary files /dev/null and b/plugins/webhook/ico.png differ
diff --git a/plugins/webhook/index.html b/plugins/webhook/index.html
new file mode 100755
index 000000000..6672a2d9e
--- /dev/null
+++ b/plugins/webhook/index.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ | 名称 |
+ 添加时间 |
+ 近期调用 |
+ 调用次数 |
+ 密钥 |
+ 操作 |
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/webhook/index.py b/plugins/webhook/index.py
new file mode 100755
index 000000000..a2fe7a073
--- /dev/null
+++ b/plugins/webhook/index.py
@@ -0,0 +1,196 @@
+# coding:utf-8
+
+import sys
+import io
+import os
+import time
+import re
+import json
+
+sys.path.append(os.getcwd() + "/class/core")
+import mw
+
+app_debug = False
+if mw.isAppleSystem():
+ app_debug = True
+
+
+def getPluginName():
+ return 'webhook'
+
+
+def getPluginDir():
+ return mw.getPluginDir() + '/' + getPluginName()
+
+
+def getServerDir():
+ return mw.getServerDir() + '/' + getPluginName()
+
+
+def getArgs():
+ args = sys.argv[2:]
+ tmp = {}
+ args_len = len(args)
+
+ if args_len == 1:
+ t = args[0].strip('{').strip('}')
+ t = t.split(':')
+ tmp[t[0]] = t[1]
+ elif args_len > 1:
+ for i in range(len(args)):
+ t = args[i].split(':')
+ tmp[t[0]] = t[1]
+
+ return tmp
+
+
+def checkArgs(data, ck=[]):
+ for i in range(len(ck)):
+ if not ck[i] in data:
+ return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
+ return (True, mw.returnJson(True, 'ok'))
+
+
+def getCfgFilePath():
+ return getServerDir() + "/cfg.json"
+
+
+def initCfg():
+ cfg = getCfgFilePath()
+ data = []
+ mw.writeFile(cfg, json.dumps(data))
+
+
+def getCfg():
+ cfg = getCfgFilePath()
+ if not os.path.exists(cfg):
+ initCfg()
+
+ data = mw.readFile(cfg)
+ data = json.loads(data)
+ return data
+
+
+def addCfg(val):
+ cfg = getCfgFilePath()
+ data = getCfg()
+ data.append(val)
+ mw.writeFile(cfg, json.dumps(data))
+
+
+def status():
+ return 'start'
+
+
+def addHook():
+ args = getArgs()
+ data = checkArgs(args, ['title', "shell"])
+ if not data[0]:
+ return data[1]
+
+ hook = {}
+ hook['title'] = args['title']
+ hook['access_key'] = mw.getRandomString(48)
+ hook['count'] = 0
+ hook['addtime'] = int(time.time())
+ hook['uptime'] = 0
+
+ script_dir = getServerDir() + "/scripts"
+ if not os.path.exists(script_dir):
+ os.mkdir(script_dir)
+
+ addCfg(hook)
+ shellFile = script_dir + '/' + hook['access_key']
+ mw.writeFile(shellFile, args['shell'])
+ return mw.returnJson(True, '添加成功!')
+
+
+def getList():
+ data = getCfg()
+
+ rdata = {}
+ rdata['list'] = data
+ rdata['script_dir'] = getServerDir() + "/scripts"
+ return mw.returnJson(True, 'ok', rdata)
+
+
+def getLog():
+ args = getArgs()
+ check_arg = checkArgs(args, ['path'])
+ if not check_arg[0]:
+ return check_arg[1]
+
+ logPath = args['path']
+
+ content = mw.getLastLine(logPath, 100)
+ return mw.returnJson(True, 'ok', content)
+
+
+def runShellArgs(args):
+ data = getCfg()
+ for i in range(len(data)):
+ if data[i]['access_key'] == args['access_key']:
+ script_dir = getServerDir() + "/scripts"
+ shellFile = script_dir + '/' + args['access_key']
+ param = ''
+ if hasattr(args, 'param'):
+ param = args['param']
+ os.system("bash {} \"{}\" >> {}.log &".format(
+ shellFile, param.replace('"', r'\"'), shellFile))
+ data[i]['count'] += 1
+ data[i]['uptime'] = int(time.time())
+ mw.writeFile(getCfgFilePath(), json.dumps(data))
+ return mw.returnJson(True, '运行成功!')
+ return mw.returnJson(False, '指定Hook不存在!')
+
+
+def runShell():
+ args = getArgs()
+ check_arg = checkArgs(args, ['access_key'])
+ if not check_arg[0]:
+ return check_arg[1]
+
+ return runShellArgs(args)
+
+
+def delHook():
+ args = getArgs()
+ check_arg = checkArgs(args, ['access_key'])
+ if not check_arg[0]:
+ return check_arg[1]
+
+ data = getCfg()
+ newdata = []
+ for hook in data:
+ if hook['access_key'] == args['access_key']:
+ continue
+ newdata.append(hook)
+
+ jsonFile = getCfgFilePath()
+ shellFile = getServerDir() + "/scripts/" + args['access_key']
+ if not os.path.exists(shellFile):
+ return mw.returnJson(False, '删除失败!')
+ os.remove(shellFile)
+ log_file = "{}.log".format(shellFile)
+ if os.path.exists(log_file):
+ os.remove(log_file)
+
+ mw.writeFile(jsonFile, json.dumps(newdata))
+ return mw.returnJson(True, '删除成功!')
+
+if __name__ == "__main__":
+ func = sys.argv[1]
+ if func == 'status':
+ print(status())
+ elif func == "add_hook":
+ print(addHook())
+ elif func == "get_list":
+ print(getList())
+ elif func == "run_shell":
+ print(runShell())
+ elif func == 'del_hook':
+ print(delHook())
+ elif func == 'get_log':
+ print(getLog())
+ else:
+ print('error')
diff --git a/plugins/webhook/info.json b/plugins/webhook/info.json
new file mode 100755
index 000000000..b4e5f279d
--- /dev/null
+++ b/plugins/webhook/info.json
@@ -0,0 +1,18 @@
+{
+ "sort": 7,
+ "ps": "WebHook,可设置回调脚本,通常用于第三方回调通知!",
+ "name": "webhook",
+ "title": "WebHook",
+ "shell": "install.sh",
+ "versions":["1.0"],
+ "updates":["1.0"],
+ "tip": "soft",
+ "checks": "server/webhook",
+ "path": "server/webhook",
+ "display": 1,
+ "author": "",
+ "date": "2022-11-02",
+ "home": "",
+ "type": 0,
+ "pid": "4"
+}
\ No newline at end of file
diff --git a/plugins/webhook/install.sh b/plugins/webhook/install.sh
new file mode 100755
index 000000000..ff52c3bee
--- /dev/null
+++ b/plugins/webhook/install.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
+export PATH
+
+curPath=`pwd`
+rootPath=$(dirname "$curPath")
+rootPath=$(dirname "$rootPath")
+serverPath=$(dirname "$rootPath")
+
+install_tmp=${rootPath}/tmp/mw_install.pl
+
+VERSION=1.0
+
+Install_App()
+{
+ echo '正在安装脚本文件...' > $install_tmp
+ mkdir -p $serverPath/webhook
+ echo "${VERSION}" > $serverPath/webhook/version.pl
+ echo '安装完成' > $install_tmp
+}
+
+Uninstall_App()
+{
+ rm -rf $serverPath/redis
+ echo "Uninstall_App" > $install_tmp
+}
+
+action=$1
+if [ "${1}" == 'install' ];then
+ Install_App
+else
+ Uninstall_App
+fi
diff --git a/plugins/webhook/js/webhook.js b/plugins/webhook/js/webhook.js
new file mode 100755
index 000000000..dbe6167f2
--- /dev/null
+++ b/plugins/webhook/js/webhook.js
@@ -0,0 +1,224 @@
+
+function whPost(method, args,callback){
+ var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
+
+ var req_data = {};
+ req_data['name'] = 'webhook';
+ req_data['func'] = method;
+
+ if (typeof(args) == 'string'){
+ req_data['args'] = JSON.stringify(toArrayObject(args));
+ } else {
+ req_data['args'] = JSON.stringify(args);
+ }
+
+ $.post('/plugins/run', req_data, function(data) {
+ layer.close(loadT);
+ if (!data.status){
+ //错误展示10S
+ layer.msg(data.msg,{icon:0,time:2000,shade: [10, '#000']});
+ return;
+ }
+
+ if(typeof(callback) == 'function'){
+ callback(data);
+ }
+ },'json');
+}
+
+function whPostCallbak(method, version, args,callback){
+ var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
+
+ var req_data = {};
+ req_data['name'] = 'webhook';
+ req_data['func'] = method;
+ args['version'] = version;
+
+ if (typeof(args) == 'string'){
+ req_data['args'] = JSON.stringify(toArrayObject(args));
+ } else {
+ req_data['args'] = JSON.stringify(args);
+ }
+
+ $.post('/plugins/callback', req_data, function(data) {
+ layer.close(loadT);
+ if (!data.status){
+ layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
+ return;
+ }
+
+ if(typeof(callback) == 'function'){
+ callback(data);
+ }
+ },'json');
+}
+
+var whEditor = null;
+
+//添加
+function addHook(){
+ layer.open({
+ type: 1,
+ area: '600px',
+ title: '添加Hook',
+ closeBtn: 1,
+ shift: 5,
+ shadeClose: false,
+ btn:['提交','关闭'],
+ content: "",
+ success:function(){
+
+ $("#hook_shell").empty().text('');
+ $(".CodeMirror").remove();
+ whEditor = CodeMirror.fromTextArea(document.getElementById("hook_shell"), {
+ extraKeys: {
+ "Ctrl-Space": "autocomplete",
+ "Ctrl-F": "findPersistent",
+ "Ctrl-H": "replaceAll",
+ "Ctrl-S": function() {}
+ },
+ lineNumbers: true,
+ matchBrackets:true,
+ mode:"sh",
+ });
+
+ $(".CodeMirror-scroll").css({"height":"300px","margin":0,"padding":0});
+ whEditor.focus();
+ },
+ yes:function(indexs){
+ var loadT = layer.msg("提交中...",{icon:16,time:0});
+ var data = {
+ title: $("#hook_title").val(),
+ shell: whEditor.getValue(),
+ }
+ whPost('add_hook', data, function(rdata){
+ var rdata = $.parseJSON(rdata.data);
+ if (!rdata.status){
+ layer.msg(rdata.msg,{icon:2});
+ return;
+ }
+ layer.close(indexs);
+ showMsg(rdata.msg, function(){
+ getHookList();
+ }, {icon:1}, 2000);
+ });
+ }
+ });
+}
+//获取列表
+function getHookList(){
+ whPost('get_list', {}, function(rdata){
+ var rdata = $.parseJSON(rdata.data);
+ var zbody = '';
+ var mlist = rdata.data.list;
+ var script_dir = rdata.data.script_dir;
+ for(var i=0;i'
+ +''+mlist[i].title+' | '
+ +''+getLocalTime(mlist[i].addtime)+' | '
+ +''+getLocalTime(mlist[i].uptime)+' | '
+ +''+mlist[i].count+' | '
+ +'查看密钥 | '
+ +'测试 | '
+ +'编辑 | '
+ +'日志 | '
+ +'删除 | '
+ +''
+ }
+ $("#zipBody").html(zbody);
+ });
+}
+
+//查看密钥
+function showWebHookCode(url,code){
+ layer.open({
+ type:1,
+ title:'查看密钥',
+ area: '600px',
+ shadeClose:false,
+ closeBtn:2,
+ content:''
+ })
+}
+
+//查看日志
+function getLogs(path){
+
+
+ whPost('get_log', {"path":path}, function(rdata){
+ var rdata = $.parseJSON(rdata.data);
+ if (!rdata.status){
+ layer.msg(rdata.msg,{icon:2});
+ }
+
+ layer.open({
+ type:1,
+ title:'任务执行日志',
+ area: ['600px','400px'],
+ shadeClose:false,
+ closeBtn:2,
+ content:'\
+ \
+
',
+ success:function(){
+ $('[name="site_logs"]').scrollTop($('[name="site_logs"]')[0].scrollHeight)
+ }
+ });
+
+
+ });
+}
+
+//运行
+function runHook(key){
+ whPost('run_shell', {"access_key":key}, function(rdata){
+ var rdata = $.parseJSON(rdata.data);
+ if (!rdata.status){
+ layer.msg(rdata.msg,{icon:2});
+ }
+
+ showMsg(rdata.msg,function(){
+ getHookList();
+ },{icon:1},2000);
+ });
+}
+//删除
+function deleteHook(key, title){
+ layer.confirm('删除Hook-['+ title +']',{
+ title:'是否删除Hook-['+ title +']任务,是否继续'
+ },function(){
+ whPost('del_hook', {"access_key":key}, function(rdata){
+ var rdata = $.parseJSON(rdata.data);
+ if (!rdata.status){
+ layer.msg(rdata.msg,{icon:2});
+ }
+
+ showMsg(rdata.msg,function(){
+ getHookList();
+ },{icon:1},2000);
+ });
+ });
+}
+
+
+
diff --git a/route/__init__.py b/route/__init__.py
index 625b2924d..ced9bbcd4 100755
--- a/route/__init__.py
+++ b/route/__init__.py
@@ -134,13 +134,29 @@ def publicObject(toObject, func, action=None, get=None):
return mw.getJson(data)
-@app.route("/debug")
-def debug():
- print(sys.version_info)
- print(session)
- os = mw.getOs()
- print(os)
- return mw.getLocalIp()
+# @app.route("/debug")
+# def debug():
+# print(sys.version_info)
+# print(session)
+# os = mw.getOs()
+# print(os)
+# return mw.getLocalIp()
+
+# 仅针对webhook插件
+@app.route("/hook")
+def webhook():
+ input_args = {
+ 'access_key': request.args.get('access_key', '').strip(),
+ 'params': request.args.get('params', '').strip()
+ }
+
+ wh_install_path = mw.getServerDir() + '/webhook'
+ if not os.path.exists(wh_install_path):
+ return mw.returnJson(False, '请先安装WebHook插件!')
+
+ sys.path.append('plugins/webhook')
+ import index
+ return index.runShellArgs(input_args)
@app.route('/close')