Compare commits

..
111 Commits
Author SHA1 Message Date
Mr Chen d6c6ae5561 Merge pull request #391 from midoks/dev
0.13.2
2023-03-09 01:49:10 +08:00
midoks a6dc15f22d 0.13.2
* supervisor添加重启功能。
* 加入滚动写入日志 mw.writeFileLog方法。
* mysql导出优化优化。
* 添加tgbot插件[仅测试]。
* TelegramBot机器人通知-加入配置。
* mariadb更新版本。
* 在线文件编辑优化。
2023-03-09 01:47:35 +08:00
midoks 360b962bd2 Update mw.py 2023-03-09 01:42:55 +08:00
midoks 37d37e0f1d Update task.py 2023-03-09 01:32:05 +08:00
midoks ddc6da9172 Update mw.py 2023-03-09 01:30:19 +08:00
midoks ceba7ab673 up 2023-03-09 01:26:39 +08:00
midoks 384704b8e5 Update mw.py 2023-03-09 01:10:04 +08:00
midoks 232d0c2f74 Update mw.py 2023-03-09 01:01:00 +08:00
midoks ef8e6f07f5 Update mw.py 2023-03-09 00:43:34 +08:00
midoks 435e565559 Update mw.py 2023-03-09 00:42:15 +08:00
midoks ec9d7e337d Update mw.py 2023-03-09 00:36:46 +08:00
midoks b5c7a2a778 Update task.py 2023-03-09 00:32:23 +08:00
midoks 72d9c9b761 Update task.py 2023-03-09 00:28:59 +08:00
midoks 30812e1fba Update task.py 2023-03-09 00:08:49 +08:00
midoks c95cb07e8d Update task.py 2023-03-09 00:05:45 +08:00
midoks f3f2ea8ef0 通知限制频率 2023-03-08 19:40:23 +08:00
midoks 9e5a5192cb Update mw.py 2023-03-08 18:02:30 +08:00
midoks 271b3d448c Update mw.py 2023-03-08 18:01:06 +08:00
midoks b7424e7195 Update config_api.py 2023-03-08 17:57:23 +08:00
midoks b607527e1f Update config_api.py 2023-03-08 17:56:18 +08:00
midoks 3c42a4e450 对通知配置进行加密处理 2023-03-08 17:56:07 +08:00
midoks b11fd9508a Update .gitignore 2023-03-08 17:29:42 +08:00
midoks dc0504cf24 Delete notify.json 2023-03-08 17:25:12 +08:00
midoks 1d8b82395f Update public.js 2023-03-08 16:25:30 +08:00
midoks 39ac55760e Update config_api.py 2023-03-08 16:20:02 +08:00
midoks ef6071956d 在线文件编辑优化 2023-03-08 16:14:28 +08:00
midoks bbbe1c84ce Update mw.py 2023-03-07 19:24:03 +08:00
midoks 064252daad Update config.html 2023-03-07 19:20:07 +08:00
midoks 3cb63c6265 Update index.html 2023-03-07 16:28:48 +08:00
midoks b541abad42 Update index.py 2023-03-07 13:44:28 +08:00
midoks 547027be0d Update install.sh 2023-03-06 23:40:56 +08:00
midoks d786b2524a up 2023-03-06 23:21:55 +08:00
midoks abac345628 Update info.json 2023-03-06 23:10:12 +08:00
midoks d4290cbdd2 mariadb更新版本 2023-03-06 22:29:20 +08:00
midoks cfd2d99e24 Update mw.py 2023-03-06 21:31:24 +08:00
midoks 28437ccfb0 Update mw.py 2023-03-06 21:30:18 +08:00
midoks 43bf755609 Update mw.py 2023-03-06 20:35:06 +08:00
midoks de225fc8b9 0.13.1.2 2023-03-06 20:28:29 +08:00
midoks 44f891f7a3 Update mw.py 2023-03-06 20:12:52 +08:00
midoks 64d1387b03 Telegram Bot机器人通知 加入配置 2023-03-06 19:32:36 +08:00
midoks 51ccbefb04 up 2023-03-06 17:15:41 +08:00
midoks 29e3017e51 up 2023-03-06 16:49:42 +08:00
midoks 197e2d80c6 Update tgbot.py 2023-03-06 16:42:29 +08:00
midoks b8f04043bc Update tgbot.service.tpl 2023-03-06 16:41:25 +08:00
midoks 2ed70b4b96 Update tgbot.py 2023-03-06 16:39:27 +08:00
midoks d056c37be5 Update index.py 2023-03-06 16:33:18 +08:00
midoks e75abae4b9 Update tgbot.service.tpl 2023-03-06 16:32:05 +08:00
midoks 3e695770d7 Update config_api.py 2023-03-06 16:26:49 +08:00
midoks 7301edbc5a 添加tgbot插件
现在只是为了获取chat_id
2023-03-06 16:19:13 +08:00
Mr Chen 704b256408 Merge pull request #390 from midoks/dev
网站统计优化
2023-03-05 18:36:57 +08:00
midoks e129051a06 Update webstats_common.lua 2023-03-05 18:34:35 +08:00
Mr Chen d38e9f7ad0 Merge pull request #389 from midoks/dev
OP防火墙优化
2023-03-05 18:07:54 +08:00
midoks c696742866 Update init.lua 2023-03-05 18:03:41 +08:00
midoks 046389df99 Update init.lua 2023-03-05 17:37:01 +08:00
midoks 3e244ed227 导出优化 2023-03-05 14:04:16 +08:00
midoks 5016aedb0f Update index.py 2023-03-05 02:08:04 +08:00
midoks c1cd45a5f3 Update my8.0.cnf 2023-03-05 00:00:59 +08:00
midoks 79c9865a5d Update index.py 2023-03-04 23:53:54 +08:00
midoks 4082f29424 加入滚动写入日志 2023-03-04 23:07:23 +08:00
midoks d777a29d8c Update update.sh 2023-03-04 21:47:12 +08:00
Mr Chen 04e43e051e Merge pull request #388 from midoks/dev
局部优化
2023-03-02 16:57:17 +08:00
midoks dffe9a77e7 Update layout.html 2023-03-02 00:57:02 +08:00
midoks 1b1462586e Update orm.py 2023-03-02 00:49:44 +08:00
midoks f11d2db761 添加重启功能 2023-03-01 18:41:32 +08:00
midoks 842c16540a Update index.py 2023-03-01 18:03:14 +08:00
midoks 614cc1032f Update webstats_log.lua 2023-03-01 14:03:46 +08:00
midoks ad46b2050e Update config.json 2023-03-01 01:40:57 +08:00
midoks 8109989927 Update layout.html 2023-02-28 19:41:13 +08:00
Mr Chen 9d9b39dfe2 Merge pull request #387 from midoks/dev
0.13.1
2023-02-28 19:11:06 +08:00
midoks 422514c40a 0.13.1
* 关闭issue,建立bbs.midoks.me。问题集中处理,发挥群众的力量。
* 添加站操作回调钩子site_cb。 网站统计和OP防火墙不再手动重载配置
* 修复ubuntu20 pureftp 安装时,端口没有加入安全里
* 增加global_static hook关键字,并优化menu的文件加载hook
* 各种细节优化。
2023-02-28 19:09:54 +08:00
midoks 632568643b Update site_api.py 2023-02-28 17:08:26 +08:00
midoks a5f29a2a6a Update cert_api.py 2023-02-28 16:26:31 +08:00
midoks b02705aa5a up 2023-02-28 03:00:46 +08:00
midoks 1f9ab560e3 Update files.js 2023-02-28 02:18:39 +08:00
midoks b3970326cd Update index.py 2023-02-28 01:57:19 +08:00
midoks f6d008e0b6 Update index.py 2023-02-28 01:50:54 +08:00
midoks 6f9a49ad7a up 2023-02-28 01:48:51 +08:00
midoks fc3c7d334a Update public.js 2023-02-28 00:17:39 +08:00
midoks 1030d1b923 site_cb 添加站操作回调钩子。 网站统计和OP防火墙不再手动重载配置 2023-02-28 00:02:16 +08:00
midoks 94d4a90bcc Update webstats_common.lua 2023-02-27 19:35:52 +08:00
midoks da4b872666 Update README.md 2023-02-27 17:57:17 +08:00
midoks cf15b19f4b Update install.sh 2023-02-26 21:46:25 +08:00
midoks aa9cdaada4 Update commit.tpl 2023-02-26 03:16:45 +08:00
midoks 659c9fe16b 修复ubuntu 20 pureftp 安装时,端口没有加入安全里 2023-02-26 02:20:06 +08:00
midoks 2b8c6d6e43 Update firewall_api.py 2023-02-26 01:39:52 +08:00
midoks 263f83088f Update firewall_api.py 2023-02-26 01:38:55 +08:00
midoks 374c938ac0 Update firewall_api.py 2023-02-26 01:38:32 +08:00
midoks 6aa73b0cae Update firewall_api.py 2023-02-26 01:36:45 +08:00
midoks 7f731ae06f Update README.md 2023-02-26 01:12:08 +08:00
midoks f87aff704c Update rhel.sh 2023-02-25 23:36:14 +08:00
midoks be9fa87133 Update rhel.sh 2023-02-25 23:31:36 +08:00
midoks de6fc19dee Create discuz.conf 2023-02-25 21:33:50 +08:00
midoks 3987c6d3dc Update config_api.py 2023-02-25 08:37:26 +08:00
midoks 96875052cd Update index.py 2023-02-25 08:25:05 +08:00
midoks 583de57f96 Update plugins_api.py 2023-02-25 08:21:20 +08:00
midoks 41b7245f03 Update plugins_api.py 2023-02-25 08:15:38 +08:00
midoks ee3684706f Update info.json 2023-02-25 07:48:32 +08:00
midoks 07936dfb81 update 2023-02-25 07:35:46 +08:00
midoks 5c46202be0 增加global_static hook关键字,并优化menu的文件加载hook
"hook":[
		{
			"tag":"global_static",
			"global_static": {
				"css_path":"menu/own_style.css",
				"js_path":"js/own_style.js"
			}
		}
	],
2023-02-25 07:26:48 +08:00
midoks 7123a15457 Update install.sh 2023-02-24 18:08:46 +08:00
midoks 4aeb45b1d5 Update install.sh 2023-02-24 17:55:13 +08:00
midoks 006a62be22 Update lib.sh 2023-02-24 17:25:04 +08:00
midoks 1e91d11125 Update mw.tpl 2023-02-24 17:22:22 +08:00
midoks 99fb4aa723 up 2023-02-24 17:14:28 +08:00
midoks 5c5bbb2da2 up 2023-02-24 17:12:31 +08:00
midoks 8b05045901 Update install.sh 2023-02-24 17:07:24 +08:00
midoks 1b73439525 Update install_dev.sh 2023-02-24 17:00:10 +08:00
midoks ec51ad016a Update install_dev.sh 2023-02-24 16:57:24 +08:00
midoks a42fae66ac Update install_dev.sh 2023-02-24 16:53:48 +08:00
midoks b4c635c2e5 Update install_dev.sh 2023-02-24 16:49:03 +08:00
midoks 9802bc5915 Update pure-ftpd.conf 2023-02-24 13:29:16 +08:00
65 changed files with 1941 additions and 256 deletions
+5 -1
View File
@@ -151,8 +151,10 @@ data/system.db-journal
data/hook_*.json
data/letsencrypt.json
data/basic_auth.json
data/notify.json
data/api.json
data/bind_domain.pl
data/unauthorized_status.pl
plugins/vip_*
plugins/own_*
@@ -162,6 +164,7 @@ plugins/openlitespeed
plugins/system_safe
plugins/tamper_proof
plugins/tamper_proof_*
plugins/cryptocurrency_trade
plugins/op_load_balance
plugins/gdrive
plugins/mtproxy
@@ -175,4 +178,5 @@ plugins/file_search
debug.out
data/unauthorized_status.pl
+9 -7
View File
@@ -29,6 +29,7 @@
基本上可以使用,后续会继续优化!欢迎提供意见!
- 吹水组 - https://t.me/mdserver_web
- 交流论坛 - https://bbs.midoks.me
```
如果出现问题,最好私给我面板信息。不要让我猜。如果不提供,不要提出问题,自行解决。 — 座右铭
@@ -98,13 +99,15 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.13.0
### 版本更新 0.13.2
* 一键迁移插件。
* 修复acme ssl申请。
* IP识别优化。
* 解决删除站点残留的问题。
* 各种细节优化。
* supervisor添加重启功能。
* 加入滚动写入日志 mw.writeFileLog方法。
* mysql导出优化优化。
* 添加tgbot插件[仅测试]。
* TelegramBot机器人通知-加入配置。
* mariadb更新版本。
* 在线文件编辑优化。
### JSDelivr安装地址
@@ -112,7 +115,6 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
curl -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/install.sh | bash
```
- 直接更新
+1 -1
View File
@@ -1522,7 +1522,7 @@ fullchain.pem 粘贴到证书输入框
self.__config['orders'][i]['auth_to'] = auth_to
# 是否到了允许重试的时间
if 'next_retry_time' in self._config['orders'][i]:
if 'next_retry_time' in self.__config['orders'][i]:
timeout = self.__config['orders'][i][
'next_retry_time'] - int(time.time())
if timeout > 0:
+78 -3
View File
@@ -27,7 +27,7 @@ from flask import request
class config_api:
__version = '0.13.0'
__version = '0.13.2'
__api_addr = 'data/api.json'
def __init__(self):
@@ -661,6 +661,60 @@ class config_api:
mw.writeLog('面板设置', '将未授权响应状态码设置为:{}'.format(status_code))
return mw.returnJson(True, '设置成功!')
def getNotifyApi(self):
# 获取
data = mw.getNotifyData(True)
return mw.returnData(True, 'ok', data)
def setNotifyApi(self):
tag = request.form.get('tag', '').strip()
data = request.form.get('data', '').strip()
cfg = mw.getNotifyData(False)
crypt_data = mw.enDoubleCrypt(tag, data)
if tag in cfg:
cfg[tag]['cfg'] = crypt_data
else:
t = {'cfg': crypt_data}
cfg[tag] = t
mw.writeNotify(cfg)
return mw.returnData(True, '设置成功')
def setNotifyTestApi(self):
# 异步通知验证
tag = request.form.get('tag', '').strip()
tag_data = request.form.get('data', '').strip()
if tag == 'tgbot':
t = json.loads(tag_data)
test_bool = mw.tgbotNotifyTest(t['app_token'], t['chat_id'])
if test_bool:
return mw.returnData(True, '验证成功')
return mw.returnData(False, '验证失败')
return mw.returnData(False, '暂时未支持该验证')
def setNotifyEnableApi(self):
# 异步通知验证
tag = request.form.get('tag', '').strip()
tag_enable = request.form.get('enable', '').strip()
data = mw.getNotifyData(False)
op_enable = True
op_action = '开启'
if tag_enable != 'true':
op_enable = False
op_action = '关闭'
if tag in data:
data[tag]['enable'] = op_enable
mw.writeNotify(data)
return mw.returnData(True, op_action + '成功')
def getPanelTokenApi(self):
api_file = self.__api_addr
tmp = mw.readFile(api_file)
@@ -824,7 +878,9 @@ class config_api:
data['username'] = mw.M('users').where(
"id=?", (1,)).getField('username')
# databases hook 获取
data['hook_tag'] = request.args.get('tag', '')
# databases hook
database_hook_file = 'data/hook_database.json'
if os.path.exists(database_hook_file):
df = mw.readFile(database_hook_file)
@@ -833,7 +889,7 @@ class config_api:
else:
data['hook_database'] = []
# menu hook 获取
# menu hook
menu_hook_file = 'data/hook_menu.json'
if os.path.exists(menu_hook_file):
df = mw.readFile(menu_hook_file)
@@ -842,4 +898,23 @@ class config_api:
else:
data['hook_menu'] = []
# global_static hook
global_static_hook_file = 'data/hook_global_static.json'
if os.path.exists(global_static_hook_file):
df = mw.readFile(global_static_hook_file)
df = json.loads(df)
data['hook_global_static'] = df
else:
data['hook_global_static'] = []
# notiy config
notify_data = mw.getNotifyData(True)
notify_tag_list = ['tgbot', 'email']
for tag in notify_tag_list:
new_tag = 'notify_' + tag + '_enable'
data[new_tag] = ''
if tag in notify_data and 'enable' in notify_data[tag]:
if notify_data[tag]['enable']:
data[new_tag] = 'checked'
return data
+10 -9
View File
@@ -123,12 +123,12 @@ class firewall_api:
address = port
if self.__isUfw:
mw.execShell('ufw delete deny from ' + address + ' to any')
elif self.__isIptables:
cmd = 'iptables -D INPUT -s ' + address + ' -j DROP'
mw.execShell(cmd)
elif self.__isFirewalld:
mw.execShell(
'firewall-cmd --permanent --remove-rich-rule=\'rule family=ipv4 source address="' + address + '" drop\'')
elif self.__isIptables:
cmd = 'iptables -D INPUT -s ' + address + ' -j DROP'
mw.execShell(cmd)
else:
pass
@@ -149,14 +149,15 @@ class firewall_api:
return mw.returnJson(False, '失败,不能删除当前面板端口!')
if self.__isUfw:
mw.execShell('ufw delete allow ' + port + '/tcp')
elif self.__isIptables:
mw.execShell(
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
elif self.__isFirewalld:
port = port.replace(':', '-')
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp')
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp')
elif self.__isIptables:
mw.execShell(
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
else:
pass
msg = mw.getInfo('删除防火墙放行端口[{1}]成功!', (port,))
@@ -438,13 +439,13 @@ class firewall_api:
def addAcceptPort(self, port):
if self.__isUfw:
mw.execShell('ufw allow ' + port + '/tcp')
elif self.__isIptables:
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
elif self.__isFirewalld:
port = port.replace(':', '-')
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp'
mw.execShell(cmd)
elif self.__isIptables:
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
else:
pass
return True
+184 -6
View File
@@ -22,6 +22,8 @@ import hashlib
import shlex
import datetime
import subprocess
import glob
import re
import db
from random import Random
@@ -80,6 +82,10 @@ def getPanelDataDir():
return getRunDir() + '/data'
def getPanelTmp():
return getRunDir() + '/tmp'
def getServerDir():
return getRootDir() + '/server'
@@ -536,6 +542,14 @@ def getDate():
return time.strftime('%Y-%m-%d %X', time.localtime())
def getDateFromNow(tf_format="%Y-%m-%d %H:%M:%S", time_zone="Asia/Shanghai"):
# 取格式时间
import time
os.environ['TZ'] = time_zone
time.tzset()
return time.strftime(tf_format, time.localtime())
def getDataFromInt(val):
time_format = '%Y-%m-%d %H:%M:%S'
time_str = time.localtime(val)
@@ -551,10 +565,39 @@ def writeLog(stype, msg, args=()):
uid = session['uid']
except Exception as e:
pass
# print(getTracebackInfo())
# writeFileLog(getTracebackInfo())
return writeDbLog(stype, msg, args, uid)
def writeFileLog(msg, path=None, limit_size=50 * 1024 * 1024, save_limit=3):
log_file = getServerDir() + '/mdserver-web/logs/debug.log'
if path != None:
log_file = path
if os.path.exists(log_file):
size = os.path.getsize(log_file)
if size > limit_size:
log_file_rename = log_file + "_" + \
time.strftime("%Y-%m-%d_%H%M%S") + '.log'
os.rename(log_file, log_file_rename)
logs = sorted(glob.glob(log_file + "_*"))
count = len(logs)
save_limit = count - save_limit
for i in range(count):
if i > save_limit:
break
os.remove(logs[i])
# print('|---多余日志[' + logs[i] + ']已删除!')
f = open(log_file, 'ab+')
msg += "\n"
if __name__ == '__main__':
print(msg)
f.write(msg.encode('utf-8'))
f.close()
return True
def writeDbLog(stype, msg, args=(), uid=1):
try:
import time
@@ -673,7 +716,7 @@ def enCrypt(key, strings):
result = f.encrypt(strings)
return result.decode('utf-8')
except:
print(getTracebackInfo())
writeFileLog(getTracebackInfo())
return strings
@@ -692,7 +735,7 @@ def deCrypt(key, strings):
result = f.decrypt(strings).decode('utf-8')
return result
except:
print(getTracebackInfo())
writeFileLog(getTracebackInfo())
return strings
@@ -711,7 +754,7 @@ def enDoubleCrypt(key, strings):
result = f.encrypt(strings)
return result.decode('utf-8')
except:
print(getTracebackInfo())
writeFileLog(getTracebackInfo())
return strings
@@ -729,7 +772,7 @@ def deDoubleCrypt(key, strings):
result = f.decrypt(strings).decode('utf-8')
return result
except:
print(getTracebackInfo())
writeFileLog(getTracebackInfo())
return strings
@@ -1533,7 +1576,7 @@ def getCertName(certPath):
result['notAfter'], "%Y-%m-%d")) - time.time()) / 86400)
return result
except Exception as e:
# print(getTracebackInfo())
writeFileLog(getTracebackInfo())
return None
@@ -1631,6 +1674,141 @@ def getMyORMDb():
o = ormDb.ORM()
return o
##################### notify start #########################################
def initNotifyConfig():
p = getNotifyPath()
if not os.path.exists(p):
writeFile(p, '{}')
return True
def getNotifyPath():
path = 'data/notify.json'
return path
def getNotifyData(is_parse=False):
initNotifyConfig()
notify_file = getNotifyPath()
notify_data = readFile(notify_file)
data = json.loads(notify_data)
if is_parse:
tag_list = ['tgbot']
for t in tag_list:
if t in data and 'cfg' in data[t]:
data[t]['data'] = json.loads(deDoubleCrypt(t, data[t]['cfg']))
return data
def writeNotify(data):
p = getNotifyPath()
return writeFile(p, json.dumps(data))
def tgbotNotifyChatID():
data = getNotifyData(True)
if 'tgbot' in data and 'enable' in data['tgbot']:
if data['tgbot']['enable']:
t = data['tgbot']['data']
return t['chat_id']
return ''
def tgbotNotifyObject():
data = getNotifyData(True)
if 'tgbot' in data and 'enable' in data['tgbot']:
if data['tgbot']['enable']:
t = data['tgbot']['data']
import telebot
bot = telebot.TeleBot(app_token)
return True, bot
return False, None
def tgbotNotifyMessage(app_token, chat_id, msg):
import telebot
bot = telebot.TeleBot(app_token)
try:
data = bot.send_message(chat_id, msg)
return True
except Exception as e:
writeFileLog(str(e))
return False
def tgbotNotifyHttpPost(app_token, chat_id, msg):
try:
url = 'https://api.telegram.org/bot' + app_token + '/sendMessage'
post_data = {
'chat_id': chat_id,
'text': msg,
}
rdata = httpPost(url, post_data)
return True
except Exception as e:
writeFileLog(str(e))
return False
def tgbotNotifyTest(app_token, chat_id):
msg = 'MW-通知验证测试OK'
return tgbotNotifyHttpPost(app_token, chat_id, msg)
def notifyMessageTry(msg, stype='common', trigger_time=300, is_write_log=True):
lock_file = getPanelTmp() + '/notify_lock.json'
if not os.path.exists(lock_file):
writeFile(lock_file, '{}')
lock_data = json.loads(readFile(lock_file))
if stype in lock_data:
diff_time = time.time() - lock_data[stype]['do_time']
if diff_time >= trigger_time:
lock_data[stype]['do_time'] = time.time()
else:
return False
else:
lock_data[stype] = {'do_time': time.time()}
writeFile(lock_file, json.dumps(lock_data))
if is_write_log:
writeLog("通知管理[" + stype + "]", msg)
data = getNotifyData(True)
# tag_list = ['tgbot', 'email']
# tagbot
do_notify = False
if 'tgbot' in data and 'enable' in data['tgbot']:
if data['tgbot']['enable']:
t = data['tgbot']['data']
i = sys.version_info
# telebot 在python小于3.7无法使用
if i[0] < 3 or i[1] < 7:
do_notify = tgbotNotifyHttpPost(
t['app_token'], t['chat_id'], msg)
else:
do_notify = tgbotNotifyMessage(
t['app_token'], t['chat_id'], msg)
return do_notify
def notifyMessage(msg, stype='common', trigger_time=300, is_write_log=True):
try:
return notifyMessageTry(msg, stype, trigger_time, is_write_log)
except Exception as e:
writeFileLog(getTracebackInfo())
return False
##################### notify end #########################################
##################### ssh start #########################################
def getSshDir():
+7 -5
View File
@@ -91,7 +91,7 @@ class plugins_api:
t = mw.readFile(menu_file)
tlist = json.loads(t)
for menu_data in tlist:
if 'path' in menu_data:
if tag == menu_data['name'] and 'path' in menu_data:
tpath = self.menuGetAbsPath(tag, menu_data['path'])
content = mw.readFile(tpath)
data['plugin_content'] = content
@@ -256,13 +256,14 @@ class plugins_api:
data = json.loads(t)
for idx in range(len(data)):
if data[idx]['title'] == info['title'] and data[idx]['name'] == info['name']:
if data[idx]['name'] == info['name']:
data.remove(data[idx])
break
mw.writeFile(hookPath, json.dumps(data))
def hookInstall(self, info):
valid_hook = ['backup', 'database']
valid_list_hook = ['menu']
valid_list_hook = ['menu', 'global_static', 'site_cb']
if 'hook' in info:
hooks = info['hook']
for h in hooks:
@@ -280,7 +281,7 @@ class plugins_api:
def hookUninstall(self, info):
valid_hook = ['backup', 'database']
valid_list_hook = ['menu']
valid_list_hook = ['menu', 'global_static', 'site_cb']
if 'hook' in info:
hooks = info['hook']
for h in hooks:
@@ -795,7 +796,8 @@ class plugins_api:
for index in range(len(tmp_data)):
plugins_info.append(tmp_data[index])
except Exception as e:
print(e)
print(json_file)
print(mw.getTracebackInfo())
start = (page - 1) * pageSize
end = start + pageSize
+33 -4
View File
@@ -72,6 +72,30 @@ class site_api:
mw.execShell("mkdir -p " + self.sslLetsDir +
" && chmod -R 755 " + self.sslLetsDir)
def runHook(self, hook_name, func_name):
# 站点操作Hook
hook_file = 'data/hook_site_cb.json'
hook_cfg = []
if os.path.exists(hook_file):
t = mw.readFile(hook_file)
hook_cfg = json.loads(t)
hook_num = len(hook_cfg)
if hook_num == 0:
return
import plugins_api
pa = plugins_api.plugins_api()
for x in range(hook_num):
hook_data = hook_cfg[x]
if func_name in hook_data:
app_name = hook_data["name"]
run_func = hook_data[func_name]['func']
# print(app_name, run_func)
pa.run(app_name, run_func)
return True
##### ----- start ----- ###
def listApi(self):
limit = request.form.get('limit', '10')
@@ -1272,6 +1296,7 @@ class site_api:
mw.M('domain').add('pid,name,port,addtime',
(pid, domain_name, domain_port, mw.getDate()))
self.runHook('site_cb', 'add')
return mw.returnJson(True, '域名添加成功!')
def addDirBindApi(self):
@@ -1401,7 +1426,7 @@ class site_api:
data['filename'] = filename
return mw.getJson(data)
# 修改物理路径
# 修改物理路径
def setPathApi(self):
mid = request.form.get('id', '')
path = request.form.get('path', '')
@@ -2530,16 +2555,18 @@ location ^~ {from} {\n\
self.createRootDir(self.sitePath)
self.nginxAddConf()
mw.M('domain').add('pid,name,port,addtime',
(pid, self.siteName, self.sitePort, mw.getDate()))
# 添加更多域名
for domain in siteMenu['domainlist']:
self.addDomain(domain, self.siteName, pid)
mw.M('domain').add('pid,name,port,addtime',
(pid, self.siteName, self.sitePort, mw.getDate()))
data = {}
data['siteStatus'] = False
mw.restartWeb()
self.runHook('site_cb', 'add')
return mw.returnJson(True, '添加成功')
def deleteWSLogs(self, webname):
@@ -2608,6 +2635,8 @@ location ^~ {from} {\n\
mw.M('binding').where("pid=?", (sid,)).delete()
mw.restartWeb()
self.runHook('site_cb', 'delete')
return mw.returnJson(True, '站点删除成功!')
def setEndDate(self, sid, edate):
+3
View File
@@ -65,6 +65,9 @@ class ORM:
def setCharset(self, charset):
self.__DB_CHARSET = charset
def setHost(self, host):
self.__DB_HOST = host
def setPort(self, port):
self.__DB_PORT = port
+5 -1
View File
@@ -33,7 +33,11 @@ if [ ! -d $WEB_PATH ];then
mkdir -p $WEB_PATH
rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
else
rsync -vauP --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
if [ -f $GIT_PROJECT_DIR/exclude.list ];then
rsync -vauP --delete --exclude-from="$GIT_PROJECT_DIR/exclude.list" $GIT_PROJECT_DIR/ $WEB_PATH
else
rsync -vauP --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
fi
fi
sysName=`uname`
+1 -1
View File
@@ -8,7 +8,7 @@
"uninstall_pre_inspection":true,
"checks": "server/mariadb",
"path": "server/mariadb",
"versions":["10.6","10.7","10.8","10.9"],
"versions":["10.6","10.7","10.8","10.9","10.11","11.0"],
"shell":"install.sh",
"checks":"server/mariadb",
"path":"server/mariadb",
+119
View File
@@ -0,0 +1,119 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.11.2
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
else
echo '安装失败' > $install_tmp
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+1 -1
View File
@@ -13,7 +13,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.6.9
MY_VER=10.6.12
Install_app()
{
+1 -1
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.7.4
MY_VER=10.7.8
Install_app()
{
+1 -1
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.8.5
MY_VER=10.8.7
Install_app()
{
+1 -1
View File
@@ -14,7 +14,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=10.9.2
MY_VER=10.9.5
Install_app()
{
+119
View File
@@ -0,0 +1,119 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#https://dev.mysql.com/downloads/mysql/5.5.html#downloads
#https://dev.mysql.com/downloads/file/?id=480541
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mariadbDir=${serverPath}/source/mariadb
MY_VER=11.0.1
Install_app()
{
mkdir -p ${mariadbDir}
echo '正在安装脚本文件...' > $install_tmp
if id mysql &> /dev/null ;then
echo "mysql uid is `id -u www`"
echo "mysql shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
else
groupadd mysql
useradd -g mysql mysql
fi
if [ "$sysName" != "Darwin" ];then
mkdir -p /var/log/mariadb
touch /var/log/mariadb/mariadb.log
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "2" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
else
cpuCore="1"
fi
# ----- cpu end ------
# if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
# wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://mirrors.aliyun.com/mariadb/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
# fi
# https://downloads.mariadb.org/interstitial/mariadb-10.9.1/source/mariadb-10.9.1.tar.gz
if [ ! -f ${mariadbDir}/mariadb-${MY_VER}.tar.gz ];then
wget --no-check-certificate -O ${mariadbDir}/mariadb-${MY_VER}.tar.gz --tries=3 https://archive.mariadb.org/mariadb-${MY_VER}/source/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d ${mariadbDir}/mariadb-${MY_VER} ];then
cd ${mariadbDir} && tar -zxvf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
fi
if [ ! -d $serverPath/mariadb ];then
cd ${mariadbDir}/mariadb-${MY_VER} && cmake \
-DCMAKE_INSTALL_PREFIX=$serverPath/mariadb \
-DMYSQL_DATADIR=$serverPath/mariadb/data/ \
-DMYSQL_USER=mysql \
-DMYSQL_UNIX_ADDR=$serverPath/mariadb/mysql.sock \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DCMAKE_C_COMPILER=/usr/bin/gcc \
-DCMAKE_CXX_COMPILER=/usr/bin/g++
make -j${cpuCore} && make install && make clean
if [ -d $serverPath/mariadb ];then
echo '10.11' > $serverPath/mariadb/version.pl
echo '安装完成' > $install_tmp
else
echo '安装失败' > $install_tmp
echo 'install fail'>&2
exit 1
fi
fi
rm -rf ${mariadbDir}/mariadb-${MY_VER}
rm -rf ${mariadbDir}/mariadb-${MY_VER}.tar.gz
}
Uninstall_app()
{
rm -rf $serverPath/mariadb
echo '卸载完成' > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_app
else
Uninstall_app
fi
+2 -1
View File
@@ -2474,7 +2474,8 @@ def doFullSyncUser(version=''):
if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + " " + sync_db + " > " + bak_file
port + " -u" + user + " -p" + apass + \
" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
+2 -1
View File
@@ -2434,7 +2434,8 @@ def doFullSyncUser(version=''):
if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p" + apass + " " + sync_db + " > " + bak_file
port + " -u" + user + " -p" + apass + \
" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
+1 -1
View File
@@ -71,7 +71,7 @@ log_replica_updates = 1
# Prevent replication from starting automatically with MySQL
#skip_replica_start = 1
#replicate-do-db
slave_skip_errors=1062
replica_skip_errors=1062
replicate-ignore-db = information_schema
replicate-ignore-db = performance_schema
replicate-ignore-db = mysql
+4 -2
View File
@@ -2665,8 +2665,10 @@ def doFullSyncUser(version=''):
writeDbSyncStatus({'code': 1, 'msg': '远程导出数据...', 'progress': 20})
if not os.path.exists(bak_file):
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p\"" + apass + "\" " + sync_db + " > " + bak_file
dump_sql_data = getServerDir() + "/bin/mysqldump " + dmp_option + " --force --opt --default-character-set=utf8 --single-transaction -h" + ip + " -P" + \
port + " -u" + user + " -p\"" + apass + \
"\" --ssl-mode=DISABLED " + sync_db + " > " + bak_file
# print(dump_sql_data)
mw.execShell(dump_sql_data)
writeDbSyncStatus({'code': 2, 'msg': '本地导入数据...', 'progress': 40})
+13 -1
View File
@@ -1,4 +1,16 @@
{
"hook":[
{
"tag":"site_cb",
"site_cb": {
"title":"网站统计",
"name":"op_waf",
"add":{"func":"reload"},
"update":{"func":"reload"},
"delete":{"func":"reload"}
}
}
],
"title":"OP防火墙",
"tip":"soft",
"name":"op_waf",
@@ -12,5 +24,5 @@
"home":"https://github.com/loveshell/ngx_lua_waf",
"date":"2019-04-21",
"pid": "1",
"versions": ["0.2.5"]
"versions": ["0.2.6"]
}
+10 -1
View File
@@ -344,13 +344,22 @@ local function waf_cc_increase()
local make_uri = "/"..make_uri_str
if params['uri_request_args']['token'] then
ngx.header.content_type = "application/json"
local args_token = params['uri_request_args']['token']
if args_token == make_token then
ngx.shared.waf_limit:set(cache_token, 1, config['safe_verify']['time'])
ngx.shared.waf_limit:set(cache_token, 1, tonumber(config['safe_verify']['time']))
local data = get_return_state(0, "ok")
ngx.say(json.encode(data))
ngx.exit(200)
end
-- C:D("debug[args]:"..tostring(params['uri_request_args']['debug']))
-- if params['uri_request_args']['debug'] == 'ok' then
-- ngx.header.content_type = "application/json"
-- local data = get_return_state(0, "ok")
-- ngx.say(json.encode(data))
-- ngx.exit(200)
-- end
end
local cc_html = ngx.re.gsub(cc_safe_js_html, "{uri}", make_uri_str)
+1 -1
View File
@@ -59,11 +59,11 @@ Install_openresty()
mkdir -p ${openrestyDir}
echo '正在安装脚本文件...' > $install_tmp
# wget -O openresty-1.21.4.1.tar.gz https://openresty.org/download/openresty-1.21.4.1.tar.gz
if [ ! -f ${openrestyDir}/openresty-${VERSION}.tar.gz ];then
wget -O ${openrestyDir}/openresty-${VERSION}.tar.gz https://openresty.org/download/openresty-${VERSION}.tar.gz
fi
cd ${openrestyDir} && tar -zxvf openresty-${VERSION}.tar.gz
# --with-openssl=$serverPath/source/lib/openssl-1.0.2q
-1
View File
@@ -26,7 +26,6 @@ AutoRename no
AnonymousCantUpload no
MaxDiskUsage 99
CustomerProof yes
PassivePortRange 48000 50000
PIDFile {$SERVER_PATH}/pureftp/etc/pure-ftpd.pid
PureDB {$SERVER_PATH}/pureftp/etc/pureftpd.pdb
+5
View File
@@ -9,6 +9,11 @@ serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
sysName=`uname`
echo "use system: ${sysName}"
+4 -3
View File
@@ -214,7 +214,8 @@ def initdStatus():
if mw.isAppleSystem():
return "Apple Computer does not support"
shell_cmd = 'systemctl status redis | grep loaded | grep "enabled;"'
shell_cmd = 'systemctl status ' + \
getPluginName() + ' | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
@@ -225,7 +226,7 @@ def initdInstall():
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl enable redis')
mw.execShell('systemctl enable ' + getPluginName())
return 'ok'
@@ -233,7 +234,7 @@ def initdUinstall():
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl disable redis')
mw.execShell('systemctl disable ' + getPluginName())
return 'ok'
+2 -13
View File
@@ -1,14 +1,3 @@
function str2Obj(str){
var data = {};
kv = str.split('&');
for(i in kv){
v = kv[i].split('=');
data[v[0]] = v[1];
}
return data;
}
function redisPost(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
@@ -18,7 +7,7 @@ function redisPost(method, version, args,callback){
req_data['version'] = version;
if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(str2Obj(args));
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
@@ -46,7 +35,7 @@ function redisPostCallbak(method, version, args,callback){
args['version'] = version;
if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(str2Obj(args));
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
+4
View File
@@ -16,6 +16,10 @@ bash ${rootPath}/scripts/getos.sh
OSNAME=`cat ${rootPath}/data/osname.pl`
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
if id www &> /dev/null ;then
echo "www uid is `id -u www`"
echo "www shell is `grep "^www:" /etc/passwd |cut -d':' -f7 `"
+127
View File
@@ -0,0 +1,127 @@
#
# Discuz Sphinx Config File
#
indexer
{
mem_limit = 32M
write_buffer = 64M
}
searchd
{
listen = 9312
listen = 9306:mysql41
log = {$SERVER_APP}/index/searchd.log
query_log = {$SERVER_APP}/index/query.log
read_timeout = 5
max_children = 0
pid_file = {$SERVER_APP}/index/searchd.pid
seamless_rotate = 1
preopen_indexes = 1
unlink_old = 1
#workers = threads # for RT to work
binlog_path = {$SERVER_APP}/index/binlog
}
source pre_forum_thread
{
type = mysql
sql_host = 127.0.0.1
sql_user = bbs
sql_pass = bbs
sql_db = bbs
sql_port = 3306
sql_query_pre = SET NAMES UTF8
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre = REPLACE INTO bbs_common_sphinxcounter SELECT 1, MAX(tid) FROM bbs_forum_thread
sql_query = SELECT t.tid as id,t.tid,t.subject,t.digest,t.displayorder,t.authorid,t.lastpost,t.special \
FROM bbs_forum_thread AS t WHERE t.tid>=$start AND t.tid<=$end
sql_query_range = SELECT (SELECT MIN(tid) FROM bbs_forum_thread),maxid FROM bbs_common_sphinxcounter WHERE indexid=1
sql_range_step = 5000
sql_attr_uint = tid
sql_attr_uint = digest
sql_attr_uint = displayorder
sql_attr_uint = authorid
sql_attr_uint = special
sql_attr_timestamp =lastpost
}
index pre_forum_thread
{
source = pre_forum_thread
path = {$SERVER_APP}/index/db/pre_forum_thread/index
min_word_len = 2
html_strip = 1
ngram_len = 1
ngram_chars = U+3000..U+2FA1F
}
# threads_minute
source pre_forum_thread_minute : pre_forum_thread
{
sql_query_pre = SET NAMES UTF8
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_range = SELECT maxid-1,(SELECT MAX(tid) FROM bbs_forum_thread) FROM bbs_common_sphinxcounter WHERE indexid=1
}
# threads_minute
index pre_forum_thread_minute : pre_forum_thread
{
source = pre_forum_thread_minute
path = {$SERVER_APP}/index/db/pre_forum_thread/pre_forum_thread_minute
}
#posts
source pre_forum_post : pre_forum_thread
{
type = mysql
sql_query_pre =
sql_query_pre = SET NAMES UTF8
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre = REPLACE INTO bbs_common_sphinxcounter SELECT 2, MAX(pid) FROM bbs_forum_post
sql_query = SELECT p.pid AS id,p.tid,p.subject,p.message,t.digest,t.displayorder,t.authorid,t.lastpost,t.special \
FROM bbs_forum_post AS p LEFT JOIN bbs_forum_thread AS t USING(tid) where p.pid >=$start and p.pid <=$end \
AND p.first=1
sql_query_range = SELECT (SELECT MIN(pid) FROM bbs_forum_post),maxid FROM bbs_common_sphinxcounter WHERE indexid=2
sql_range_step = 5000
sql_attr_uint = tid
sql_attr_uint = digest
sql_attr_uint= displayorder
sql_attr_uint = authorid
sql_attr_uint = special
sql_attr_timestamp = lastpost
}
#posts
index pre_forum_post
{
source = pre_forum_post
path = {$SERVER_APP}/index/db/pre_forum_thread/pre_forum_post
min_word_len = 2
html_strip = 1
ngram_len = 1
ngram_chars = U+3000..U+2FA1F
}
#pre_forum_post_minute
source pre_forum_post_minute : pre_forum_post
{
sql_query_pre = SET NAMES UTF8
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_range = SELECT maxid-1,(SELECT MAX(pid) FROM bbs_forum_post) FROM bbs_common_sphinxcounter WHERE indexid=2
}
#pre_forum_post_minute
index pre_forum_post_minute : pre_forum_post
{
source = pre_forum_thread
path = {$SERVER_APP}/index/db/pre_forum_thread/pre_forum_post_minute
}
+1 -1
View File
@@ -23,7 +23,7 @@
.code span {display: block;margin-left: 15px;margin-bottom: 0;}
</style>
<script type="text/javascript">
resetPluginWinWidth(800);
resetPluginWinWidth(850);
$.getScript( "/plugins/file?name=supervisor&f=js/supervisor.js", function(){
pluginService('supervisor');
});
+28 -3
View File
@@ -220,7 +220,8 @@ def getSupList():
infos = fr.readlines()
for line in infos:
if "command=" in line.strip():
d["command"] = line.strip().split('=')[1]
# d["command"] = line.strip().split('=')[1]
d["command"] = "子配置查看"
if "user=" in line.strip():
d["user"] = line.strip().split('=')[1]
if "priority=" in line.strip():
@@ -329,6 +330,27 @@ def startJob():
return mw.returnJson(True, action + '[' + name + ']成功!')
def restartJob():
args = getArgs()
data = checkArgs(args, ['name', 'status'])
if not data[0]:
return data[1]
supCtl = 'supervisorctl -c ' + getServerDir() + "/supervisor.conf"
name = args['name']
status = args['status']
cmd = supCtl + " stop " + name
data = mw.execShell(cmd)
cmd = supCtl + " start " + name
data = mw.execShell(cmd)
if data[1] != '':
return mw.returnJson(False, '[' + name + ']重启失败!')
return mw.returnJson(True, '[' + name + ']重启成功!')
def delJob():
args = getArgs()
data = checkArgs(args, ['name'])
@@ -440,8 +462,9 @@ def configTpl():
pathFile = os.listdir(path)
tmp = []
for one in pathFile:
file = path + '/' + one
tmp.append(file)
if one.endswith(".ini"):
file = path + '/' + one
tmp.append(file)
return mw.getJson(tmp)
@@ -567,6 +590,8 @@ if __name__ == "__main__":
print(addJob())
elif func == 'start_job':
print(startJob())
elif func == 'restart_job':
print(restartJob())
elif func == 'del_job':
print(delJob())
elif func == 'update_job':
+11
View File
@@ -70,6 +70,7 @@ function supList(page, search){
list += '<td style="text-align:right">\
<a href="javascript:;" class="btlink" onclick="startOrStop(\''+rdata.data[i]['program']+'\',\''+sup_status+'\')" title="启动|停止">'+sup_status_desc+'</a> | ' +
'<a href="javascript:;" class="btlink" onclick="restartJob(\''+rdata.data[i]['program']+'\',\''+sup_status+'\')" title="重启">重启</a> | ' +
'<a href="javascript:;" class="btlink" onclick="updateJob(\''+rdata.data[i]['program']+'\')">修改</a> | ' +
'<a href="javascript:;" class="btlink" onclick="delJob(\''+rdata.data[i]['program']+'\')" title="删除">删除</a>' +
'</td>';
@@ -128,6 +129,16 @@ function startOrStop(name,status){
});
}
function restartJob(name,status){
myPost('restart_job',{'name':name,'status':status}, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg,{icon:rdata.status?1:2});
setTimeout(function(){
supList(1,10);
},2000);
});
}
function updateJob(name){
myPost('get_job_info',{'name':name},function(data){
var rdata = $.parseJSON(data.data);
Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

+25
View File
@@ -0,0 +1,25 @@
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('tgbot');">服务</p>
<p onclick="pluginInitD('tgbot');">自启动</p>
<p onclick="botConf();">Bot配置</p>
<p onclick="pluginLogs('tgbot','','run_log');">日志</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<style>
.conf_p span{
width: 70px;
}
</style>
<script type="text/javascript">
resetPluginWinHeight(300);
$.getScript( "/plugins/file?name=tgbot&f=js/tgbot.js", function(){
pluginService('tgbot');
});
</script>
+245
View File
@@ -0,0 +1,245 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
import base64
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'tgbot'
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 getConfigData():
cfg_path = getServerDir() + "/data.cfg"
if not os.path.exists(cfg_path):
mw.writeFile(cfg_path, '{}')
t = mw.readFile(cfg_path)
return json.loads(t)
def writeConf(data):
cfg_path = getServerDir() + "/data.cfg"
mw.writeFile(cfg_path, json.dumps(data))
return True
def getInitDTpl():
path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl"
return path
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
if t.strip() == '':
tmp = []
else:
t = t.split(':')
tmp[t[0]] = t[1]
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 status():
data = mw.execShell(
"ps -ef|grep tgbot |grep -v grep | grep -v mdserver-web | awk '{print $2}'")
if data[0] == '':
return 'stop'
return 'start'
def initDreplace():
file_tpl = getInitDTpl()
service_path = mw.getServerDir()
app_path = service_path + '/' + getPluginName()
initD_path = getServerDir() + '/init.d'
if not os.path.exists(initD_path):
os.mkdir(initD_path)
file_bin = initD_path + '/' + getPluginName()
# initd replace
# if not os.path.exists(file_bin):
content = mw.readFile(file_tpl)
content = content.replace('{$SERVER_PATH}', service_path + '/mdserver-web')
content = content.replace('{$APP_PATH}', app_path)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
# systemd
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/tgbot.service'
systemServiceTpl = getPluginDir() + '/init.d/tgbot.service.tpl'
if os.path.exists(systemDir) and not os.path.exists(systemService):
service_path = mw.getServerDir()
se_content = mw.readFile(systemServiceTpl)
se_content = se_content.replace('{$APP_PATH}', app_path)
mw.writeFile(systemService, se_content)
mw.execShell('systemctl daemon-reload')
return file_bin
def tbOp(method):
file = initDreplace()
if not mw.isAppleSystem():
data = mw.execShell('systemctl ' + method + ' ' + getPluginName())
if data[1] == '':
return 'ok'
return data[1]
data = mw.execShell(file + ' ' + method)
print(data)
# if data[1] == '':
# return 'ok'
return 'ok'
def start():
return tbOp('start')
def stop():
return tbOp('stop')
def restart():
status = tbOp('restart')
return status
def reload():
tgbot_tpl = getPluginDir() + '/startup/tgbot.py'
tgbot_dst = getServerDir() + '/tgbot.py'
content = mw.readFile(tgbot_tpl)
mw.writeFile(tgbot_dst, content)
return tbOp('reload')
def initdStatus():
if mw.isAppleSystem():
return "Apple Computer does not support"
shell_cmd = 'systemctl status ' + \
getPluginName() + ' | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initdInstall():
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl enable ' + getPluginName())
return 'ok'
def initdUinstall():
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl disable ' + getPluginName())
return 'ok'
def getBotConf():
data = getConfigData()
if 'bot' in data:
return mw.returnJson(True, 'ok', data['bot'])
return mw.returnJson(False, 'ok', {})
def setBotConf():
args = getArgs()
data_args = checkArgs(args, ['app_token'])
if not data_args[0]:
return data_args[1]
data = getConfigData()
args['app_token'] = base64.b64decode(args['app_token']).decode('ascii')
data['bot'] = args
writeConf(data)
return mw.returnJson(True, '保存成功!', [])
def runLog():
p = getServerDir() + '/task.log'
return p
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 == 'get_bot_conf':
print(getBotConf())
elif func == 'set_bot_conf':
print(setBotConf())
elif func == 'run_log':
print(runLog())
else:
print('error')
+17
View File
@@ -0,0 +1,17 @@
{
"sort": 7,
"ps": "[<b style='color:red;'>DEV</b>]简单Telegram机器人",
"name": "tgbot",
"title": "tgbot",
"shell": "install.sh",
"versions":["0.1"],
"tip": "soft",
"checks": "server/tgbot",
"path": "server/tgbot",
"display": 1,
"author": "Zend",
"date": "2023-03-06",
"home": "https://core.telegram.org/bots/api",
"type": 0,
"pid": "5"
}
+14
View File
@@ -0,0 +1,14 @@
[Unit]
Description=Tgbot Service
After=network.target
[Service]
Type=forking
ExecStart={$APP_PATH}/init.d/tgbot start
ExecStop={$APP_PATH}/init.d/tgbot stop
ExecReload={$APP_PATH}/init.d/tgbot reload
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
+85
View File
@@ -0,0 +1,85 @@
#!/bin/sh
# chkconfig: 2345 55 25
# description: Tgbot Service
### BEGIN INIT INFO
# Provides: Tgbot
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts Tgbot
# Description: starts the MDW-Web
### END INIT INFO
# Simple Tgbot init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
PATH=/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export LANG=en_US.UTF-8
mw_path={$SERVER_PATH}
PATH=$PATH:$mw_path/bin
if [ -f $mw_path/bin/activate ];then
source $mw_path/bin/activate
fi
tg_start(){
isStart=`ps -ef|grep 'tgbot.py' |grep -v grep | awk '{print $2}'`
if [ "$isStart" == '' ];then
echo -e "starting tgbot... \c"
cd $mw_path
python3 {$APP_PATH}/tgbot.py >> {$APP_PATH}/task.log &
isStart=""
while [[ "$isStart" == "" ]];
do
echo -e ".\c"
sleep 0.5
isStart=`ps -ef|grep 'tgbot.py' |grep -v grep | awk '{print $2}'`
let n+=1
if [ $n -gt 20 ];then
break;
fi
done
if [ "$isStart" == '' ];then
echo -e "\033[31mfailed\033[0m"
echo -e "\033[31mError: tgbot service startup failed.\033[0m"
return;
fi
echo -e "\033[32mdone\033[0m"
else
echo "starting tgbot...(pid $(echo $isStart)) already running"
fi
}
tg_stop(){
echo -e "stopping tgbot ... \c";
arr=`ps aux|grep 'tgbot.py'|grep -v grep|awk '{print $2}'`
for p in ${arr[@]}
do
kill -9 $p > /dev/null 2>&1
done
echo -e "\033[32mdone\033[0m"
}
case "$1" in
start)
tg_start
;;
stop)
tg_stop
;;
restart|reload)
tg_stop
sleep 0.3
tg_start
;;
*)
echo "Please use start or stop as first argument"
;;
esac
+59
View File
@@ -0,0 +1,59 @@
#!/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=$2
# pip3 install ccxt
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
pip3 install pyTelegramBotAPI
pip3 install telebot
Install_App()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
mkdir -p $serverPath/tgbot
echo "${VERSION}" > $serverPath/tgbot/version.pl
cp -rf ${rootPath}/plugins/tgbot/startup/* $serverPath/tgbot
cd ${rootPath} && python3 ${rootPath}/plugins/tgbot/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/tgbot/index.py initd_install
echo '安装完成' > $install_tmp
}
Uninstall_App()
{
if [ -f /usr/lib/systemd/system/tgbot.service ];then
systemctl stop tgbot
systemctl disable tgbot
rm -rf /usr/lib/systemd/system/tgbot.service
systemctl daemon-reload
fi
if [ -f $serverPath/tgbot/initd/tgbot ];then
$serverPath/tgbot/initd/tgbot stop
fi
rm -rf $serverPath/tgbot
echo "Uninstall_redis" > $install_tmp
}
action=$1
if [ "${1}" == 'install' ];then
Install_App
else
Uninstall_App
fi
+78
View File
@@ -0,0 +1,78 @@
function appPost(method, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'tgbot';
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(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function appPostCallbak(method, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
var req_data = {};
req_data['name'] = 'tgbot';
req_data['func'] = method;
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');
}
function botConf(){
appPost('get_bot_conf','',function(data){
var rdata = $.parseJSON(data.data);
var app_token = 'app_token';
if(rdata['status']){
db_data = rdata['data'];
app_token = db_data['app_token'];
}
var mlist = '';
mlist += '<p><span>app_token</span><input style="width: 250px;" class="bt-input-text mr5" name="app_token" value="'+app_token+'" type="text"><font>必填写</font></p>'
var option = '<style>.conf_p p{margin-bottom: 2px}</style>\
<div class="conf_p" style="margin-bottom:0">\
' + mlist + '\
<div style="margin-top:10px; padding-right:15px" class="text-right">\
<button class="btn btn-success btn-sm" onclick="submitBotConf()">保存</button>\
</div>\
</div>';
$(".soft-man-con").html(option);
});
}
function submitBotConf(){
var pull_data = {};
pull_data['app_token'] = base64_encode($('input[name="app_token"]').val());
appPost('set_bot_conf',pull_data,function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata['msg'],{icon:rdata['status']?1:2,time:2000,shade: [0.3, '#000']});
});
}
+81
View File
@@ -0,0 +1,81 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
import base64
sys.path.append(os.getcwd() + "/class/core")
import mw
import telebot
def getPluginName():
return 'tgbot'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getConfigData():
cfg_path = getServerDir() + "/data.cfg"
if not os.path.exists(cfg_path):
mw.writeFile(cfg_path, '{}')
t = mw.readFile(cfg_path)
return json.loads(t)
def writeConf(data):
cfg_path = getServerDir() + "/data.cfg"
mw.writeFile(cfg_path, json.dumps(data))
return True
def writeLog(log_str):
if __name__ == "__main__":
print(log_str)
log_file = getServerDir() + '/task.log'
mw.writeFileLog(log_str, log_file, limit_size=5 * 1024)
return True
# start tgbot
cfg = getConfigData()
while True:
cfg = getConfigData()
if 'bot' in cfg and 'app_token' in cfg['bot']:
if cfg['bot']['app_token'] != '' and cfg['bot']['app_token'] != 'app_token':
break
writeLog('等待输入配置,填写app_token')
time.sleep(3)
bot = telebot.TeleBot(cfg['bot']['app_token'])
# from telebot.async_telebot import AsyncTeleBot
# import asyncio
# bot = AsyncTeleBot(cfg['bot']['app_token'])
@bot.message_handler(commands=['start', 'help'])
def hanle_start_help(message):
bot.reply_to(message, "hello world")
@bot.message_handler(commands=['chat_id'])
def hanle_get_chat_id(message):
bot.reply_to(message, message.chat.id)
writeLog('启动成功')
bot.polling()
# asyncio.run(bot.polling())
+19 -18
View File
@@ -25,7 +25,7 @@ class App():
self.__host_dir = self.getServerDir() + '/host'
if not os.path.exists(self.__host_dir):
os.makedirs(self.__host_dir)
mw.execShell('mkdir -p ' + self.__host_dir)
def getPluginName(self):
return 'webssh'
@@ -145,24 +145,25 @@ class App():
def get_server_list(self):
host_list = []
for name in os.listdir(self.__host_dir):
info_file = self.__host_dir + '/' + name + '/info.json'
if not os.path.exists(info_file):
continue
try:
info_tmp = self.getSshInfo(info_file)
host_info = {}
host_info['host'] = name
host_info['port'] = info_tmp['port']
host_info['ps'] = info_tmp['ps']
# host_info['sort'] = int(info_tmp['sort'])
except Exception as e:
print(e)
# if os.path.exists(info_file):
# os.remove(info_file)
# continue
if os.path.exists(self.__host_dir):
for name in os.listdir(self.__host_dir):
info_file = self.__host_dir + '/' + name + '/info.json'
if not os.path.exists(info_file):
continue
try:
info_tmp = self.getSshInfo(info_file)
host_info = {}
host_info['host'] = name
host_info['port'] = info_tmp['port']
host_info['ps'] = info_tmp['ps']
# host_info['sort'] = int(info_tmp['sort'])
except Exception as e:
print(e)
# if os.path.exists(info_file):
# os.remove(info_file)
# continue
host_list.append(host_info)
host_list.append(host_info)
host_list = sorted(host_list, key=lambda x: x['host'], reverse=False)
return mw.returnJson(True, 'ok!', host_list)
+8
View File
@@ -9,6 +9,14 @@
"css_path":"menu/index.css",
"js_path":"js/webssh.js"
}
},
{
"tag":"global_static",
"global_static": {
"title":"终端管理",
"name":"webssh",
"css_path":"menu/ico.css"
}
}
],
"id":3,
+10
View File
@@ -0,0 +1,10 @@
/* menu start */
.menu .menu_plugin_webssh {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAMBJREFUeNpiYKAQMM6cOVMASBuQozk9Pf0AC5AuAOJ6cgwAWt7IhMQvRKIfAPEEYgxhQWL3o9EFpBgwAeifQhKdD7YI5oWPUMEEmAQR4COyATBwAIgdgIacB2IFYkxhQouWB0BsCA3E86QGIsxvDSBXgGIDSxr5ALTgAk4XADWAQt4fiB2BChcAaQVoGoHheLwuAGqagBz/UNsciQ4DEgE/zAUfQM4DOt+eRANAYTMRZADIrxfIdMUFSnMzA0CAAQD0hjqnYxWD2gAAAABJRU5ErkJggg==");
}
.menu .current .menu_plugin_webssh:hover {
background-image: url("data:image/gif;base64,R0lGODlhEAAQAMQXAJ6ipUFITySRPIiMkDFRQuXm5jJKQy1kQCGeOzBXQSl3PiWLPVhfZSxrQCpxP9na2yeEPTREQ8LExmRqb5OXm/Hx8TU9RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjMyQjYwMTU3OTA2QTExRUJCN0NFQUUwQjRDMzM4RDJDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjMyQjYwMTU4OTA2QTExRUJCN0NFQUUwQjRDMzM4RDJDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MzJCNjAxNTU5MDZBMTFFQkI3Q0VBRTBCNEMzMzhEMkMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzJCNjAxNTY5MDZBMTFFQkI3Q0VBRTBCNEMzMzhEMkMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFMgAXACwAAAAAEAAQAAAFU6AljmRpBVOqrqtFVXAsy9Q7VMMDzHHN/5UawGQC1CiWg4IoOiINAoGB6BxBENSjyIE4oFKMprYhIFgYkvTQpWWOqm6RcVBI2+/2AuXL6k8CcSYhACH5BAUyABcALAcACQAFAAIAAAUIYJSMBLGcSggAIfkEBTIAFwAsBwAJAAUAAgAABQhgMI0MI51ACAAh+QQFMgAXACwHAAkABQACAAAFCGCUjASxnEoIADs=");
}
/* menu end */
-11
View File
@@ -1,15 +1,4 @@
/* menu start */
.menu .menu_plugin_webssh {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAMBJREFUeNpiYKAQMM6cOVMASBuQozk9Pf0AC5AuAOJ6cgwAWt7IhMQvRKIfAPEEYgxhQWL3o9EFpBgwAeifQhKdD7YI5oWPUMEEmAQR4COyATBwAIgdgIacB2IFYkxhQouWB0BsCA3E86QGIsxvDSBXgGIDSxr5ALTgAk4XADWAQt4fiB2BChcAaQVoGoHheLwuAGqagBz/UNsciQ4DEgE/zAUfQM4DOt+eRANAYTMRZADIrxfIdMUFSnMzA0CAAQD0hjqnYxWD2gAAAABJRU5ErkJggg==");
}
.menu .current .menu_plugin_webssh:hover {
background-image: url("data:image/gif;base64,R0lGODlhEAAQAMQXAJ6ipUFITySRPIiMkDFRQuXm5jJKQy1kQCGeOzBXQSl3PiWLPVhfZSxrQCpxP9na2yeEPTREQ8LExmRqb5OXm/Hx8TU9RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjMyQjYwMTU3OTA2QTExRUJCN0NFQUUwQjRDMzM4RDJDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjMyQjYwMTU4OTA2QTExRUJCN0NFQUUwQjRDMzM4RDJDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MzJCNjAxNTU5MDZBMTFFQkI3Q0VBRTBCNEMzMzhEMkMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzJCNjAxNTY5MDZBMTFFQkI3Q0VBRTBCNEMzMzhEMkMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4B//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAAAh+QQFMgAXACwAAAAAEAAQAAAFU6AljmRpBVOqrqtFVXAsy9Q7VMMDzHHN/5UawGQC1CiWg4IoOiINAoGB6BxBENSjyIE4oFKMprYhIFgYkvTQpWWOqm6RcVBI2+/2AuXL6k8CcSYhACH5BAUyABcALAcACQAFAAIAAAUIYJSMBLGcSggAIfkEBTIAFwAsBwAJAAUAAgAABQhgMI0MI51ACAAh+QQFMgAXACwHAAkABQACAAAFCGCUjASxnEoIADs=");
}
/* menu end */
.xterm{
position: inherit;
}
+1
View File
@@ -27,6 +27,7 @@
"gif",
"jpg",
"css",
"svg",
"js",
"ico",
"woff2"
+5 -4
View File
@@ -191,8 +191,10 @@ def pSqliteDb(dbname='web_logs', site_name='unset', name="logs"):
conn = mw.M(dbname).dbPos(db_dir, name)
conn.execute("PRAGMA synchronous = 0")
conn.execute("PRAGMA page_size = 4096")
conn.execute("PRAGMA cache_size = 8000")
conn.execute("PRAGMA page_size = 32768")
conn.execute("PRAGMA journal_mode = wal")
conn.execute("PRAGMA journal_size_limit = 1073741824")
return conn
@@ -263,6 +265,8 @@ def initDreplace():
loadLuaSiteFile()
loadDebugLogFile()
if not mw.isAppleSystem():
mw.execShell("chown -R www:www " + getServerDir())
return 'ok'
@@ -277,9 +281,6 @@ def start():
import tool_task
tool_task.createBgTask()
if not mw.isAppleSystem():
mw.execShell("chown -R www:www " + getServerDir())
# issues:326
luaRestart()
return 'ok'
+14 -2
View File
@@ -1,10 +1,22 @@
{
"sort": 7,
"hook":[
{
"tag":"site_cb",
"site_cb": {
"title":"网站统计",
"name":"webstats",
"add":{"func":"reload"},
"update":{"func":"reload"},
"delete":{"func":"reload"}
}
}
],
"sort": "7",
"ps": "网站统计报表",
"name": "webstats",
"title": "网站统计",
"shell": "install.sh",
"versions":["0.2.4"],
"versions":["0.2.5"],
"tip": "soft",
"install_pre_inspection":true,
"checks": "server/webstats",
+26 -6
View File
@@ -239,6 +239,7 @@ function _M.cronPre(self)
local time_key = self:get_store_key()
local time_key_next = self:get_store_key_with_time(ngx.time()+3600)
for site_k, site_v in ipairs(sites) do
local input_sn = site_v["name"]
@@ -250,16 +251,24 @@ function _M.cronPre(self)
'spider_stat'
}
local v1 = true
local v2 = true
for _,ws_v in pairs(wc_stat) do
self:_update_stat_pre(db, ws_v, time_key)
self:_update_stat_pre(db, ws_v, time_key_next)
v1 = self:_update_stat_pre(db, ws_v, time_key)
v2 = self:_update_stat_pre(db, ws_v, time_key_next)
end
if db and db:isopen() then
db:execute([[COMMIT]])
db:close()
end
if not v1 or not v2 then
return false
end
end
return true
end
-- 后台任务
@@ -273,7 +282,12 @@ function _M.cron(self)
return true
end
self:cronPre()
-- self:D("dedebide:cron task is busy!")
local ready_ok = self:cronPre()
if not ready_ok then
self:D("cron task is busy!")
return true
end
ngx.update_time()
local begin = ngx.now()
@@ -653,9 +667,14 @@ end
function _M._update_stat_pre(self, db, stat_table, key)
local local_sql = string.format("INSERT INTO %s(time) SELECT :time WHERE NOT EXISTS(SELECT time FROM %s WHERE time=:time);", stat_table, stat_table)
local update_stat_stmt = db:prepare(local_sql)
update_stat_stmt:bind_names{time=key}
update_stat_stmt:step()
update_stat_stmt:finalize()
if update_stat_stmt then
update_stat_stmt:bind_names{time=key}
update_stat_stmt:step()
update_stat_stmt:finalize()
return true
end
return false
end
function _M.update_stat_quick(self, db, stat_table, key,columns)
@@ -1084,6 +1103,7 @@ end
function _M.get_client_ip(self)
local client_ip = "unknown"
local cdn = auto_config['cdn']
local request_header = ngx.req.get_headers()
if cdn == true then
for _,v in ipairs(auto_config['cdn_headers']) do
if request_header[v] ~= nil and request_header[v] ~= "" then
+1
View File
@@ -134,6 +134,7 @@ log_by_lua_block {
local function exclude_url()
if not ngx.var.uri then return false end
if not ngx.var.request_uri then return false end
if not auto_config['exclude_url'] then return false end
local the_uri = string.sub(ngx.var.request_uri, 2)
local url_conf = auto_config["exclude_url"]
+2
View File
@@ -29,3 +29,5 @@ flask-caching>=1.10.1
bcrypt==3.1.3
PyMySQL==1.0.2
whitenoise==5.3.0
pyTelegramBotAPI
telebot
+72
View File
@@ -354,6 +354,78 @@ function setPanelSSL(){
});
}
function setNotifyApi(tag, obj){
var enable = $(obj).prop("checked");
console.log(tag,obj,enable);
$.post('/config/set_notify_enable', {'tag':tag, 'enable':enable},function(rdata){
showMsg(rdata.msg, function(){
if (rdata.status){}
} ,{icon:rdata.status?1:2}, 1000);
},'json');
}
function getTgbot(){
var loadT = layer.msg('正在获取TgBot信息...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/config/get_notify',{},function(data){
layer.close(loadT);
var app_token = '';
var chat_id = '';
if (data.status){
if (typeof(data['data']['tgbot']) !='undefined'){
app_token = data['data']['tgbot']['data']['app_token'];
chat_id = data['data']['tgbot']['data']['chat_id'];
}
}
layer.open({
type: 1,
area: "500px",
title: '配置TgBot配置',
closeBtn: 1,
shift: 5,
btn:["确定","关闭","验证"],
shadeClose: false,
content: "<div class='bt-form pd20'>\
<div class='line'>\
<span class='tname'>APP_TOKEN</span>\
<div class='info-r'><input class='bt-input-text' type='text' name='app_token' value='"+app_token+"' style='width:100%'/></div>\
</div>\
<div class='line'>\
<span class='tname'>CHAT_ID</span>\
<div class='info-r'><input class='bt-input-text' type='text' name='chat_id' value='"+chat_id+"' style='width:100%' /></div>\
</div>\
</div>",
yes:function(index){
var pdata = {};
pdata['app_token'] = $('input[name="app_token"]').val();
pdata['chat_id'] = $('input[name="chat_id"]').val();
$.post('/config/set_notify',{'tag':'tgbot', 'data':JSON.stringify(pdata)},function(rdata){
showMsg(rdata.msg, function(){
if (rdata.status){
layer.close(index);
}
},{icon:rdata.status?1:2},2000);
});
},
btn3:function(index){
var pdata = {};
pdata['app_token'] = $('input[name="app_token"]').val();
pdata['chat_id'] = $('input[name="chat_id"]').val();
$.post('/config/set_notify_test',{'tag':'tgbot', 'data':JSON.stringify(pdata)},function(rdata){
showMsg(rdata.msg, function(){
if (rdata.status){
layer.close(index);
}
},{icon:rdata.status?1:2},2000);
});
return false;
}
});
});
}
function getPanelSSL(){
var loadT = layer.msg('正在获取证书信息...',{icon:16,time:0,shade: [0.3, '#000']});
+1 -1
View File
@@ -1110,7 +1110,7 @@ function reName(type, fileName) {
</div>',
success:function(){
$("#newFileName").focus().keyup(function(e){
if(e.keyCode == 13) $("#ReNameBtn").click();
if(e.keyCode == 13) $(".layui-layer-btn0").click();
});
},
yes:function(){
+227 -70
View File
@@ -515,29 +515,24 @@ function openPath(a) {
window.location.href = "/files/"
}
function onlineEditFile(k, f) {
function onlineEditFile(k, f, callback) {
if(k != 0) {
var l = $("#PathPlace input").val();
var h = encodeURIComponent($("#textBody").val());
var a = $("select[name=encoding]").val();
var loadT = layer.msg(lan.bt.save_file, {
icon: 16,
time: 0
});
$.post("/files/save_body", "data=" + h + "&path=" + encodeURIComponent(f) + "&encoding=" + a, function(m) {
var loadT = layer.msg('正在保存,请稍候...', {icon: 16,time: 0});
$.post("/files/save_body", "data=" + h + "&path=" + encodeURIComponent(f) + "&encoding=" + a, function(data) {
if(k == 1) {
layer.close(loadT);
}
layer.msg(m.msg, {
icon: m.status ? 1 : 2
});
layer.msg(data.msg, {icon: data.status ? 1 : 2});
if (data.status && typeof(callback) == 'function'){
callback(k, f);
}
},'json');
return
}
var e = layer.msg(lan.bt.read_file, {
icon: 16,
time: 0
});
var e = layer.msg('正在读取文件,请稍候...', {icon: 16,time: 0});
var g = f.split(".");
var b = g[g.length - 1];
var d;
@@ -595,15 +590,12 @@ function onlineEditFile(k, f) {
default:
var j = {
name: "htmlmixed",
scriptTypes: [{
matches: /\/x-handlebars-template|\/x-mustache/i,
mode: null
}, {
matches: /(text|application)\/(x-)?vb(a|script)/i,
mode: "vbscript"
}]
scriptTypes: [
{matches: /\/x-handlebars-template|\/x-mustache/i,mode: null},
{matches: /(text|application)\/(x-)?vb(a|script)/i,mode: "vbscript"}
]
};
d = j
d = j;
}
$.post("/files/get_body", "path=" + encodeURIComponent(f), function(s) {
if(s.status === false){
@@ -619,51 +611,57 @@ function onlineEditFile(k, f) {
m = s.data.encoding == u[p] ? "selected" : "";
n += '<option value="' + u[p] + '" ' + m + ">" + u[p] + "</option>";
}
var code_mirror = null;
var r = layer.open({
type: 1,
shift: 5,
closeBtn: 1,
area: ["90%", "90%"],
title: lan.bt.edit_title+"[" + f + "]",
content: '<form class="bt-form pd20 pb70">\
btn:['保存','关闭'],
title: "在线编辑[" + f + "]",
content: '<form class="bt-form pd20">\
<div class="line">\
<p style="color:red;margin-bottom:10px">' + lan.bt.edit_ps + '\
<p style="color:red;margin-bottom:10px">提示:Ctrl+F 搜索关键字,Ctrl+G 查找下一个,Ctrl+S 保存,Ctrl+Shift+R 查找替换!\
<select class="bt-input-text" name="encoding" style="width: 74px;position: absolute;top: 31px;right: 19px;height: 22px;z-index: 9999;border-radius: 0;">' + n + '</select>\
</p>\
<textarea class="mCustomScrollbar bt-input-text" id="textBody" style="width:100%;margin:0 auto;line-height: 1.8;position: relative;top: 10px;" value="" />\
</div>\
<div class="bt-form-submit-btn" style="position:absolute; bottom:0; width:100%">\
<button type="button" class="btn btn-danger btn-sm btn-editor-close">'+lan.public.close+'</button>\
<button id="OnlineEditFileBtn" type="button" class="btn btn-success btn-sm">'+lan.public.save+'</button>\
</div>\
</form>'
});
$("#textBody").text(s.data.data);
var q = $(window).height() * 0.9;
$("#textBody").height(q - 160);
var t = CodeMirror.fromTextArea(document.getElementById("textBody"), {
extraKeys: {
"Ctrl-F": "findPersistent",
"Ctrl-H": "replaceAll",
"Ctrl-S": function() {
$("#textBody").text(t.getValue());
onlineEditFile(2, f)
}
</form>',
success:function(){
$("#textBody").text(s.data.data);
var q = $(window).height() * 0.9;
$("#textBody").height(q - 160);
code_mirror = CodeMirror.fromTextArea(document.getElementById("textBody"), {
extraKeys: {
"Ctrl-F": "findPersistent",
"Ctrl-H": "replaceAll",
"Ctrl-S": function() {
$("#textBody").text(code_mirror.getValue());
onlineEditFile(2, f,callback);
},
"Cmd-S":function() {
$("#textBody").text(code_mirror.getValue());
onlineEditFile(2, f,callback);
},
},
mode: d,
lineNumbers: true,
matchBrackets: true,
matchtags: true,
autoMatchParens: true
});
code_mirror.focus();
code_mirror.setSize("auto", q - 150);
$(window).resize(function(){
var q = $(window).height() * 0.9;
code_mirror.setSize("auto", q - 150);
});
},
mode: d,
lineNumbers: true,
matchBrackets: true,
matchtags: true,
autoMatchParens: true
});
t.focus();
t.setSize("auto", q - 150);
$("#OnlineEditFileBtn").click(function() {
$("#textBody").text(t.getValue());
onlineEditFile(1, f);
});
$(".btn-editor-close").click(function() {
layer.close(r);
yes:function(){
$("#textBody").text(code_mirror.getValue());
onlineEditFile(1, f,callback);
}
});
},'json');
}
@@ -1133,18 +1131,21 @@ function bindPanel(a,type,ip,btid,url,user,pw){
<li><font style='color:red'>注意,开启广告拦截会导致无法快捷登录。</font></li></ul>\
</div>\
<div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm' onclick=\"layer.closeAll()\">关闭</button> "+btn+"</div>\
</div>"
});
$("#btaddress").on("input",function(){
var str =$(this).val();
var isip = /([\w-]+\.){2,6}\w+/;
var iptext = str.match(isip);
if(iptext) $("#bttitle").val(iptext[0]);
}).blur(function(){
var str =$(this).val();
var isip = /([\w-]+\.){2,6}\w+/;
var iptext = str.match(isip);
if(iptext) $("#bttitle").val(iptext[0]);
</div>",
success:function(){
$("#btaddress").on("input",function(){
var str =$(this).val();
var isip = /([\w-]+\.){2,6}\w+/;
var iptext = str.match(isip);
if(iptext) $("#bttitle").val(iptext[0]);
}).blur(function(){
var str =$(this).val();
var isip = /([\w-]+\.){2,6}\w+/;
var iptext = str.match(isip);
if(iptext) $("#bttitle").val(iptext[0]);
});
}
});
}
//删除快捷登录
@@ -1769,6 +1770,159 @@ function entitiesDecode(text) {
return text;
}
// base64.js
// base64加密
function base64_encode(str) {
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var out, i, len;
var c1, c2, c3;
len = str.length;
i = 0;
out = "";
while(i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if(i == len)
{
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt((c1 & 0x3) << 4);
out += "==";
break;
}
c2 = str.charCodeAt(i++);
if(i == len)
{
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt((c2 & 0xF) << 2);
out += "=";
break;
}
c3 = str.charCodeAt(i++);
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
out += base64EncodeChars.charAt(c3 & 0x3F);
}
return out;
}
// base64解密
function base64_decode(str) {
var base64DecodeChars = new Array(
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
var c1, c2, c3, c4;
var i, len, out;
len = str.length;
i = 0;
out = "";
while(i < len) {
/* c1 */
do {
c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
} while(i < len && c1 == -1);
if(c1 == -1)
break;
/* c2 */
do {
c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
} while(i < len && c2 == -1);
if(c2 == -1)
break;
out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
/* c3 */
do {
c3 = str.charCodeAt(i++) & 0xff;
if(c3 == 61)
return out;
c3 = base64DecodeChars[c3];
} while(i < len && c3 == -1);
if(c3 == -1)
break;
out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
/* c4 */
do {
c4 = str.charCodeAt(i++) & 0xff;
if(c4 == 61)
return out;
c4 = base64DecodeChars[c4];
} while(i < len && c4 == -1);
if(c4 == -1)
break;
out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
}
return out;
}
function utf16to8(str) {
var out, i, len, c;
out = "";
len = str.length;
for(i = 0; i < len; i++) {
c = str.charCodeAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out += str.charAt(i);
} else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
} else {
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}
}
return out;
}
function utf8to16(str) {
var out, i, len, c;
var char2, char3;
out = "";
len = str.length;
i = 0;
while(i < len) {
c = str.charCodeAt(i++);
switch(c >> 4)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
out += str.charAt(i-1);
break;
case 12: case 13:
// 110x xxxx 10xx xxxx
char2 = str.charCodeAt(i++);
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = str.charCodeAt(i++);
char3 = str.charCodeAt(i++);
out += String.fromCharCode(((c & 0x0F) << 12) |
((char2 & 0x3F) << 6) |
((char3 & 0x3F) << 0));
break;
}
}
return out;
}
function pluginService(_name, version){
var data = {name:_name, func:'status'}
@@ -2120,6 +2274,8 @@ function pluginOpInitD(a, _version, b) {
}
function pluginLogs(_name, version, func, line){
var _this = this;
if ( typeof(version) == 'undefined' ){
version = '';
}
@@ -2160,9 +2316,10 @@ function pluginLogs(_name, version, func, line){
if(rdata.data == '') {
rdata.data = '当前没有日志!';
}
var ebody = '<div class="soft-man-con">\
<textarea readonly="" style="margin: 0px;width: 100%;height: 520px;background-color: #333;color:#fff; padding:0 5px" id="info_log">'+rdata.data+'</textarea>\
</div>';
var h = parseInt($('.bt-w-menu').css('height')) - 40;
var ebody = '<textarea readonly="" style="margin: 0px;height: '+h+'px;width: 100%;background-color: #333;color:#fff; padding:0 5px" id="info_log">'+rdata.data+'</textarea>';
$(".soft-man-con").html(ebody);
var ob = document.getElementById('info_log');
ob.scrollTop = ob.scrollHeight;
+15 -1
View File
@@ -102,7 +102,6 @@
</div>
<div class="title c6 plr15"><h3 class="f16">安全</h3></div>
<div class="setting-con pd15">
<p class="mtb15">
@@ -148,6 +147,21 @@
<span class="set-info c7">为非管理员临时提供面板访问权限</span>
</p>
</div>
<div class="title c6 plr15"><h3 class="f16">通知</h3></div>
<div class="setting-con pd15">
<p class="mtb15">
<span class="set-tit text-right" title="TelegramBot" style="float: left;">TG机器人通知</span>
<input id="cfg_tgbot" name="cfg_tgbot" onclick="setNotifyApi('tgbot',this)" class="btswitch btswitch-ios" type="checkbox" {{data['notify_tgbot_enable']}}>
<label class="btswitch-btn ml5" for="cfg_tgbot" style="float: left;margin-top:4px;"></label>
<button ype="button" class="btn btn-default btn-xs panel_api_btn" style="vertical-align: middle; margin-left: 10px" onclick="getTgbot();">TelegramBot配置</button>
<span class="set-info c7">Telegram Bot机器人通知【<b style="color:red;">国内可能无法使用</b>】</span>
</p>
</div>
</div>
</div>
</div>
+47 -30
View File
@@ -2,35 +2,42 @@
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="renderer" content="webkit">
<title>{{data['title']}}</title>
<link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon" />
<link href="/static/bootstrap-3.3.5/css/bootstrap.min.css?v={{config.version}}" rel="stylesheet">
<link href="/static/css/site.css?v={{config.version}}" rel="stylesheet">
<link href="/static/codemirror/lib/codemirror.css?v={{config.version}}" rel="stylesheet">
<script src="/static/language/Simplified_Chinese/lan.js?v={{config.version}}"></script>
<!--[if lte IE 9]>
<script src="/static/js/requestAnimationFrame.js"></script>
<![endif]-->
<!-- 统计一下用户量,让我的开发更有激情 -->
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-FC74BB2RGD"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-FC74BB2RGD');
</script>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="renderer" content="webkit">
<title>{{data['title']}}</title>
<link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon" />
<link href="/static/bootstrap-3.3.5/css/bootstrap.min.css?v={{config.version}}" rel="stylesheet">
<link href="/static/css/site.css?v={{config.version}}" rel="stylesheet">
<link href="/static/codemirror/lib/codemirror.css?v={{config.version}}" rel="stylesheet">
<script src="/static/language/Simplified_Chinese/lan.js?v={{config.version}}"></script>
<!--[if lte IE 9]>
<script src="/static/js/requestAnimationFrame.js"></script>
<![endif]-->
<!-- 统计一下用户量,让我的开发更有激情 -->
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-FC74BB2RGD"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-FC74BB2RGD');
</script>
{% for menu in data['hook_menu'] %}
{% if menu['js_path'] %}
<!-- 加载插件css -->
<link href="/plugins/file?name={{menu['name']}}&v={{config.version}}&f={{menu['css_path']}}" rel="stylesheet" />
{% endif %}
{% endfor %}
{% for menu in data['hook_menu'] %}
{% if menu['css_path'] and data['hook_tag'] == menu['name'] %}
<!-- 加载插件css -->
<link href="/plugins/file?name={{menu['name']}}&v={{config.version}}&f={{menu['css_path']}}" rel="stylesheet" />
{% endif %}
{% endfor %}
<!-- 全局静态HOOK -->
{% for menu in data['hook_global_static'] %}
{% if menu['css_path'] %}
<link href="/plugins/file?name={{menu['name']}}&v={{config.version}}&f={{menu['css_path']}}" rel="stylesheet" />
{% endif %}
{% endfor %}
</head>
<body>
@@ -83,11 +90,15 @@
{% block content %}{% endblock %}
<div class="footer bgw">mdserver-web &copy;2018-∞ Linux面板 (<a class="btlink" target="_blank" href="//github.com/midoks/mdserver-web">源码</a>) <span style="margin-left:5px;">/</span>
<a class="btlink" style="margin-left:5px;" href="//github.com/midoks/mdserver-web/wiki" target="_blank">WIKI</a><span style="margin-left:5px;">/</span>
<a class="btlink" target="_blank" style="margin-left:5px;" href="//github.com/midoks/mdserver-web/wiki">WIKI</a><span style="margin-left:5px;">/</span>
<a class='btlink panel_ad_list_mode' style="margin-left:5px;">AD</a>
<span style="margin-left:5px;">/</span>
<a class='btlink' target="_blank" href="https://bbs.midoks.me" style="margin-left:5px;">交流论坛</a>
<span style="margin-left:5px;">/</span>
<a class='btlink' target="_blank" href="https://t.me/mdserver_web" style="margin-left:5px;">TG吹水群</a>
</div>
</div>
</div>
</div>
</body>
<script type="text/javascript">
@@ -158,8 +169,14 @@ if (thisPath.indexOf('?')>-1){
<script src="/static/laydate/laydate.js?v={{config.version}}"></script>
{% for menu in data['hook_menu'] %}
{% if menu['js_path'] and data['hook_tag'] == menu['name'] %}
<script src="/plugins/file?name={{menu['name']}}&f={{menu['js_path']}}&v={{config.version}}"></script>
{% endif %}
{% endfor %}
<!-- 全局静态HOOK -->
{% for menu in data['hook_global_static'] %}
{% if menu['js_path'] %}
<!-- 加载插件js -->
<script src="/plugins/file?name={{menu['name']}}&f={{menu['js_path']}}&v={{config.version}}"></script>
{% endif %}
{% endfor %}
+24 -12
View File
@@ -196,32 +196,44 @@ error_logs()
mw_update()
{
cn=$(curl --insecure -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ];then
curl --insecure -fsSL https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/update.sh | bash
else
LOCAL_ADDR=common
ping -c 1 github.com > /dev/null 2>&1
if [ "$?" != "0" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "common" ];then
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/master/scripts/update.sh | bash
else
curl --insecure -fsSL https://gitee.com/midoks/mdserver-web/raw/master/scripts/install.sh | bash
fi
}
mw_update_dev()
{
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ];then
curl --insecure -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/update_dev.sh | bash
else
LOCAL_ADDR=common
ping -c 1 github.com > /dev/null 2>&1
if [ "$?" != "0" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "common" ];then
curl --insecure -fsSL https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/update_dev.sh | bash
else
curl --insecure -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/update_dev.sh | bash
fi
cd /www/server/mdserver-web
}
mw_mirror()
{
cn=$(curl --insecure -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ];then
bash <(curl --insecure -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)
else
LOCAL_ADDR=common
ping -c 1 github.com > /dev/null 2>&1
if [ "$?" != "0" ];then
LOCAL_ADDR=cn
fi
if [ "$LOCAL_ADDR" == "common" ];then
bash <(curl --insecure -sSL https://raw.githubusercontent.com/midoks/change-linux-mirrors/main/change-mirrors.sh)
else
bash <(curl --insecure -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh)
fi
cd /www/server/mdserver-web
}
+17 -14
View File
@@ -56,6 +56,16 @@ else
fi
# cn=$(curl --insecure -fsSL -m 10 https://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
LOCAL_ADDR=common
ping -c 1 github.com > /dev/null 2>&1
if [ "$?" != "0" ];then
LOCAL_ADDR=cn
HTTP_PREFIX="https://ghproxy.com/"
fi
if [ $OSNAME != "macos" ];then
if id www &> /dev/null ;then
echo ""
@@ -71,11 +81,8 @@ if [ $OSNAME != "macos" ];then
mkdir -p /www/backup/site
# https://cdn.jsdelivr.net/gh/midoks/mdserver-web@latest/scripts/install.sh
cn=$(curl --insecure -fsSL -m 10 https://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -d /www/server/mdserver-web ];then
if [ ! -z "$cn" ];then
if [ "$LOCAL_ADDR" != "common" ];then
curl -sSLo /tmp/master.zip https://gitee.com/midoks/mdserver-web/repository/archive/master.zip
else
curl -sSLo /tmp/master.zip https://codeload.github.com/midoks/mdserver-web/zip/master
@@ -89,8 +96,8 @@ if [ $OSNAME != "macos" ];then
# install acme.sh
if [ ! -d /root/.acme.sh ];then
if [ ! -z "$cn" ];then
curl -sSL -o /tmp/acme.tar.gz https://ghproxy.com/github.com/acmesh-official/acme.sh/archive/master.tar.gz
if [ "$LOCAL_ADDR" != "common" ];then
curl -sSLo /tmp/acme.tar.gz https://gitee.com/neilpang/acme.sh/repository/archive/master.tar.gz
tar xvzf /tmp/acme.tar.gz -C /tmp
cd /tmp/acme.sh-master
bash acme.sh install
@@ -103,17 +110,13 @@ if [ $OSNAME != "macos" ];then
fi
fi
echo "use system version: ${OSNAME}"
if [ "${OSNAME}" == "macos" ];then
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
if [ ! -z "$cn" ];then
HTTP_PREFIX="https://ghproxy.com/"
if [ "$LOCAL_ADDR" != "common" ];then
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/install/macos.sh | bash
else
curl -fsSL ${HTTP_PREFIX}https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install/macos.sh | bash
fi
curl -fsSL ${HTTP_PREFIX}https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install/macos.sh | bash
else
cd /www/server/mdserver-web && bash scripts/install/${OSNAME}.sh
fi
+1 -4
View File
@@ -83,9 +83,6 @@ if [ ! -f /usr/sbin/firewalld ];then
#取消服务锁定
systemctl unmask firewalld
systemctl start firewalld
sed -i 's#AllowZoneDrifting=yes#AllowZoneDrifting=no#g' /etc/firewalld/firewalld.conf
firewall-cmd --reload
# look
# firewall-cmd --list-all
@@ -102,7 +99,7 @@ if [ ! -f /usr/sbin/firewalld ];then
# firewall-cmd --permanent --zone=public --add-port=3306/tcp
# firewall-cmd --permanent --zone=public --add-port=30000-40000/tcp
# sed -i 's#AllowZoneDrifting=yes#AllowZoneDrifting=no#g' /etc/firewalld/firewalld.conf
sed -i 's#AllowZoneDrifting=yes#AllowZoneDrifting=no#g' /etc/firewalld/firewalld.conf
firewall-cmd --reload
#安装时不开启
+15 -5
View File
@@ -74,7 +74,6 @@ fi
# HTTP_PREFIX="https://ghproxy.com/"
# fi
if [ $OSNAME != "macos" ];then
mkdir -p /www/server
mkdir -p /www/wwwroot
@@ -83,7 +82,13 @@ if [ $OSNAME != "macos" ];then
mkdir -p /www/backup/site
if [ ! -d /www/server/mdserver-web ];then
curl -sSLo /tmp/dev.zip ${HTTP_PREFIX}github.com/midoks/mdserver-web/archive/refs/heads/dev.zip
if [ "$LOCAL_ADDR" == "common" ];then
curl -sSLo /tmp/dev.zip ${HTTP_PREFIX}github.com/midoks/mdserver-web/archive/refs/heads/dev.zip
else
curl -sSLo /tmp/dev.zip https://gitee.com/midoks/mdserver-web/repository/archive/dev.zip
fi
cd /tmp && unzip /tmp/dev.zip
mv -f /tmp/mdserver-web-dev /www/server/mdserver-web
rm -rf /tmp/dev.zip
@@ -92,8 +97,9 @@ if [ $OSNAME != "macos" ];then
# install acme.sh
if [ ! -d /root/.acme.sh ];then
if [ "$HTTP_PREFIX" == "https://ghproxy.com/" ];then
curl -sSL -o /tmp/acme.tar.gz ${HTTP_PREFIX}github.com/acmesh-official/acme.sh/archive/master.tar.gz
if [ "$LOCAL_ADDR" != "common" ];then
# curl -sSL -o /tmp/acme.tar.gz ${HTTP_PREFIX}github.com/acmesh-official/acme.sh/archive/master.tar.gz
curl -sSLo /tmp/acme.tar.gz https://gitee.com/neilpang/acme.sh/repository/archive/master.tar.gz
tar xvzf /tmp/acme.tar.gz -C /tmp
cd /tmp/acme.sh-master
bash acme.sh install
@@ -109,7 +115,11 @@ fi
echo "use system version: ${OSNAME}"
if [ "${OSNAME}" == "macos" ];then
curl -fsSL ${HTTP_PREFIX}raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install/macos.sh | bash
if [ "$LOCAL_ADDR" != "common" ];then
curl -fsSL https://gitee.com/midoks/mdserver-web/raw/dev/scripts/install/macos.sh | bash
else
curl -fsSL ${HTTP_PREFIX}https://raw.githubusercontent.com/midoks/mdserver-web/dev/scripts/install/macos.sh | bash
fi
else
cd /www/server/mdserver-web && bash scripts/install/${OSNAME}.sh
fi
+10 -2
View File
@@ -47,9 +47,17 @@ else
echo "OK"
fi
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
# cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
LOCAL_ADDR=common
ping -c 1 github.com > /dev/null 2>&1
if [ "$?" != "0" ];then
LOCAL_ADDR=cn
HTTP_PREFIX="https://ghproxy.com/"
fi
PIPSRC="https://pypi.python.org/simple"
if [ ! -z "$cn" ];then
if [ "$LOCAL_ADDR" != "common" ];then
PIPSRC="https://pypi.tuna.tsinghua.edu.cn/simple"
fi
+12 -3
View File
@@ -55,8 +55,17 @@ else
fi
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ];then
# cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
LOCAL_ADDR=common
ping -c 1 github.com > /dev/null 2>&1
if [ "$?" != "0" ];then
LOCAL_ADDR=cn
HTTP_PREFIX="https://ghproxy.com/"
fi
if [ "$LOCAL_ADDR" != "common" ];then
curl -sSLo /tmp/master.zip https://gitee.com/midoks/mdserver-web/repository/archive/master.zip
else
curl -sSLo /tmp/master.zip https://codeload.github.com/midoks/mdserver-web/zip/master
@@ -69,7 +78,7 @@ CP_CMD=/usr/bin/cp
if [ -f /bin/cp ];then
CP_CMD=/bin/cp
fi
$CP_CMD -rf /tmp/mdserver-web-dev/* /www/server/mdserver-web
$CP_CMD -rf /tmp/mdserver-web-master/* /www/server/mdserver-web
rm -rf /tmp/master.zip
rm -rf /tmp/mdserver-web-master
+10 -2
View File
@@ -54,8 +54,16 @@ else
OSNAME='unknow'
fi
cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
if [ ! -z "$cn" ];then
# cn=$(curl -fsSL -m 10 http://ipinfo.io/json | grep "\"country\": \"CN\"")
HTTP_PREFIX="https://"
LOCAL_ADDR=common
ping -c 1 github.com > /dev/null 2>&1
if [ "$?" != "0" ];then
LOCAL_ADDR=cn
HTTP_PREFIX="https://ghproxy.com/"
fi
if [ "$LOCAL_ADDR" != "common" ];then
curl -sSLo /tmp/dev.zip https://gitee.com/midoks/mdserver-web/repository/archive/dev.zip
else
curl -sSLo /tmp/dev.zip https://github.com/midoks/mdserver-web/archive/refs/heads/dev.zip
+7
View File
@@ -256,6 +256,13 @@ def systemTask():
tmp = {}
# 取当前CPU Io
tmp['used'] = psutil.cpu_percent(interval=1)
if tmp['used'] > 80:
panel_title = mw.getConfig('title')
ip = mw.getHostAddr()
now_time = mw.getDateFromNow()
msg = now_time + '|节点[' + panel_title + ':' + ip + \
']处于高负载[' + str(tmp['used']) + '],请排查原因!'
mw.notifyMessage(msg, '面板监控', 600)
if not cpuInfo:
tmp['mem'] = sm.getMemUsed()