webhook 1.0

pull/241/head
midoks 3 years ago
parent 105f12cba6
commit 8ed36c1781
  1. 242
      plugins/memcached/bak/index_2022_6_18.py
  2. BIN
      plugins/webhook/ico.png
  3. 32
      plugins/webhook/index.html
  4. 196
      plugins/webhook/index.py
  5. 18
      plugins/webhook/info.json
  6. 33
      plugins/webhook/install.sh
  7. 224
      plugins/webhook/js/webhook.js
  8. 30
      route/__init__.py

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

@ -0,0 +1,32 @@
<style>
.help{
background-color: #f6f6f6;
border: 1px solid #dedede;
border-radius: 3px;
line-height: 24px;
margin-top: 20px;
padding: 10px;
}
</style>
<div class="divtable pd20">
<button class="btn btn-success btn-sm" style="margin-bottom: 5px;" onclick="addHook()">添加Hook</button>
<table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">
<thead>
<tr>
<th>名称</th>
<th>添加时间</th>
<th>近期调用</th>
<th>调用次数</th>
<th>密钥</th>
<th style="text-align: right;" width="150">操作</th>
</tr>
</thead>
<tbody id="zipBody"></tbody>
</table>
</div>
<script type="text/javascript">
$.getScript( "/plugins/file?name=webhook&f=js/webhook.js",function() {
getHookList();
});
</script>

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

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

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

@ -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: "<div class='bt-form pd20'>\
<div class='line'>\
<span class='tname'>名称</span>\
<div class='info-r'><input class='bt-input-text' placeholder='Hook名称' type='text' id='hook_title' name='title' style='width:380px' /></div>\
</div>\
<div class='line'>\
<span class='tname'>执行脚本</span>\
<div class='info-r'>\
<textarea id='hook_shell' style='width:380px; height:300px;border:1px solid #ccc;font-size:15px'></textarea>\
</div>\
</div>\
</div>",
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.length;i++){
zbody += '<tr>'
+'<td>'+mlist[i].title+'</td>'
+'<td>'+getLocalTime(mlist[i].addtime)+'</td>'
+'<td>'+getLocalTime(mlist[i].uptime)+'</td>'
+'<td>'+mlist[i].count+'</td>'
+'<td><a href="javascript:showWebHookCode(\''+mlist[i].url+'\',\''+mlist[i].access_key+'\')" class="btlink">查看密钥</a></td>'
+'<td><a href="javascript:runHook(\''+mlist[i].access_key+'\');" class="btlink">测试</a> | '
+'<a href="javascript:onlineEditFile(0,\''+ script_dir + '/'+ mlist[i].access_key+'\',\'sh\');" class="btlink">编辑</a> | '
+'<a href="javascript:getLogs(\''+ script_dir + '/' + mlist[i].access_key+'.log\');" class="btlink">日志</a> | '
+'<a href="javascript:deleteHook(\''+mlist[i].access_key+'\',\''+ mlist[i].title +'\');" class="btlink">删除</a></td>'
+'</tr>'
}
$("#zipBody").html(zbody);
});
}
//查看密钥
function showWebHookCode(url,code){
layer.open({
type:1,
title:'查看密钥',
area: '600px',
shadeClose:false,
closeBtn:2,
content:'<div class="bt-form pd20">\
<div class="line"><span class="tname" style="width:50px">密钥</span><input class="bt-input-text mr5" disabled="disabled" value="'+ code +'" style="width:420px" /><button class="btn btn-success btn-sm" onclick="bt.pub.copy_pass(\''+ code +'\')">复制密钥</button></div>\
<div class="line help">\
<b>WebHook使用方法:</b><br>\
GET/POST:<br>\
'+window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '')+'/hook?access_key='+code+'&amp;param=aaa<br>\
@param access_key string HOOK密钥<br>\
@param param string 自定义参数在hook脚本中使用$1接收<br>\
</div>\
</div>'
})
}
//查看日志
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:'<div class="bt-logs" style="font-size:0;">\
<textarea class="bt-input-text mr20 site_logs pd10" name="site_logs" style="width:100%;line-height:22px;white-space: pre-line;font-size:12px;height:358px;border: none;" readonly="readonly">'+ (rdata.data || '当前没有日志.') +'</textarea>\
</div>',
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);
});
});
}

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

Loading…
Cancel
Save