增加新功能

This commit is contained in:
晚风拂柳颜 2023-06-09 15:10:22 +08:00
parent 1e022cb1a5
commit 089da0eaae
4 changed files with 187 additions and 86 deletions

View File

@ -24,6 +24,7 @@ from utils.common_api import js_render
admin = Blueprint("admin", __name__)
# @admin.route("/",methods=['get'])
# def index():
# return R.ok(msg='欢迎进入首页',data=None)
@ -46,7 +47,9 @@ def admin_index(): # 管理员界面
# print(rules)
cache_count = getCacheCount()
# print(cache_count)
return render_template('admin.html',js0_password=js0_password, pystate=use_py,rules=rules,cache_count=cache_count, ver=getLocalVer(), live_url=live_url)
return render_template('admin.html', js0_password=js0_password, pystate=use_py, rules=rules,
cache_count=cache_count, ver=getLocalVer(), live_url=live_url)
@admin.route('/settings')
def admin_settings(): # 管理员界面
@ -58,6 +61,7 @@ def admin_settings(): # 管理员界面
# print(conf_lists)
return render_template('settings.html', conf_lists=conf_lists, ver=getLocalVer())
@admin.route('/save_conf', methods=['POST'])
def admin_save_conf(): # 管理员界面
if not verfy_token():
@ -70,6 +74,7 @@ def admin_save_conf(): # 管理员界面
res_id = lsg.setItem(key, value)
return R.success(f'修改成功,记录ID为:{res_id}')
@admin.route('/update_env', methods=['POST'])
def admin_update_env(): # 更新环境变量中的某个值
if not verfy_token():
@ -81,6 +86,7 @@ def admin_update_env(): # 更新环境变量中的某个值
ENV = update_env(key, value)
return R.success(f'修改成功,最新的完整ENV见data', data=ENV)
@admin.route("/edit/<name>", methods=['GET'])
def admin_edit_rule(name):
# print(name)
@ -88,6 +94,27 @@ def admin_edit_rule(name):
return render_template('login.html')
return render_template('edit_rule.html', name=name)
@admin.route("/save_edit/<name>", methods=['POST'])
def admin_save_edit_rule(name):
# print(name)
if not verfy_token():
return R.error('请登录后再试')
code = getParmas('code')
file_path = os.path.abspath(f'js/{name}')
if 'var rule' not in code and name != '模板.js':
return R.error(f'文件{name}保存失败,未检测到关键词:var rule')
if not os.path.exists(file_path):
return R.error('服务端没有此文件!' + file_path)
logger.info(f'待保存文件路径:{file_path}')
with open(file_path, mode='w+', encoding='utf-8') as f:
f.write(code)
return R.success(f'保存成功')
@admin.route("/view/<name>", methods=['GET'])
def admin_view_rule(name):
return js_render(name)
@ -123,6 +150,7 @@ def admin_view_rule(name):
# except Exception as e:
# return R.error(f'非法猥亵\n{e}')
@admin.route('/clear/<name>')
def admin_clear_rule(name):
if not name or not name.split('.')[-1] in ['js', 'txt', 'py', 'json']:
@ -137,6 +165,7 @@ def admin_clear_rule(name):
os.remove(file_path)
return R.ok('成功删除文件:' + file_path)
@admin.route('/get_ver')
def admin_get_ver():
if not verfy_token():
@ -147,6 +176,7 @@ def admin_get_ver():
online_ver, msg = getOnlineVer(update_proxy)
return jsonify({'local_ver': getLocalVer(), 'online_ver': online_ver, 'msg': msg})
@admin.route('/update_db')
def admin_update_db():
if not verfy_token():
@ -165,6 +195,7 @@ def admin_update_db():
logger.info(f'cmd执行结果:{result}')
return R.success('数据库升级完毕')
@admin.route('/update_ver')
def admin_update_ver():
if not verfy_token():
@ -174,6 +205,7 @@ def admin_update_ver():
msg = download_new_version(update_proxy)
return R.success(msg)
@admin.route('/rule_state/<int:state>', methods=['POST'])
def admin_rule_state(state=0): # 管理员修改规则状态
if not verfy_token():
@ -196,6 +228,7 @@ def admin_rule_state(state=0): # 管理员修改规则状态
return R.success(f'修改成功,服务器反馈信息为:{success_list}')
@admin.route('/rule_order/<int:order>', methods=['POST'])
def admin_rule_order(order=0): # 管理员修改规则顺序
if not verfy_token():
@ -219,6 +252,7 @@ def admin_rule_order(order=0): # 管理员修改规则顺序
return R.success(f'修改成功,服务器反馈信息为:{success_list}')
@admin.route('/parse/save_data', methods=['POST'])
def admin_parse_save_data(): # 管理员保存拖拽排序后的解析数据
if not verfy_token():
@ -264,6 +298,7 @@ def admin_parse_save_data(): # 管理员保存拖拽排序后的解析数据
# print(len(success_list))
return R.success(f'修改成功,服务器反馈信息为:{success_list}')
@admin.route('/force_update')
def admin_force_update():
if not verfy_token():
@ -276,6 +311,7 @@ def admin_force_update():
msg = '升级失败。具体原因只能去看实时日志(通过9001端口)'
return R.failed(msg)
@admin.route('/update_lives')
def admin_update_lives():
url = getParmas('url')
@ -290,6 +326,7 @@ def admin_update_lives():
else:
return R.failed(f'直播源{live_url}同步失败')
@admin.route('/write_live_url')
def admin_write_live_url():
url = getParmas('url')
@ -302,6 +339,7 @@ def admin_write_live_url():
msg = f'已修改的配置记录id为:{id}'
return R.success(msg)
@admin.route('/change_use_py')
def admin_change_use_py():
if not verfy_token():
@ -314,6 +352,7 @@ def admin_change_use_py():
msg = f'已修改的配置记录id为:{id},结果为{state}'
return R.success(msg)
# @admin.route('/get_use_py')
# def admin_get_use_py():
# if not verfy_token():
@ -360,6 +399,7 @@ def upload_file():
# return render_template('upload.html')
return R.failed('文件上传失败')
@admin.route('/login', methods=['GET', 'POST'])
def login_api():
username = getParmas('username')
@ -377,12 +417,14 @@ def login_api():
else:
return R.failed('登录失败,用户名或密码错误')
@admin.route('/logtail')
def admin_logtail():
if not verfy_token():
return R.failed('请登录后再试')
return render_template('logtail.html')
@admin.route('/lives')
def admin_lives():
if not verfy_token():
@ -393,6 +435,7 @@ def admin_lives():
# 不带http的前缀 host
# 当前路径 path
host_url = request.host_url
def get_lives():
base_path = os.path.dirname(os.path.abspath(__file__)) # 当前文件所在目录
# print(base_path)
@ -401,7 +444,8 @@ def admin_lives():
files = os.listdir(live_path)
# print(files)
# files = list(filter(lambda x: str(x).endswith('.txt') and str(x).find('模板') < 0, files))
files = list(filter(lambda x: str(x).split('.')[-1] in ['txt','json','m3u'] and str(x).find('模板') < 0, files))
files = list(
filter(lambda x: str(x).split('.')[-1] in ['txt', 'json', 'm3u'] and str(x).find('模板') < 0, files))
files = [f'{host_url}lives?path=txt/lives/{file}' for file in files]
return files

View File

@ -1,3 +1,6 @@
###### 2023/06/09
- [X] 发布新版本,增加上传源覆盖提示,增加在线编辑源功能(手机使用可能在此界面会卡死,推荐电脑)
###### 2023/06/08
- [X] 后台管理增加优选源功能。参考config.py进行配置优选源参数
配置好优选源后在动态的在线配置链接ver=2后面添加参数 &sp=1 可以开启优选结果

View File

@ -1 +1 @@
3.9.43beta3
3.9.43beta4

View File

@ -14,29 +14,85 @@
<link href="/static/plugin/codemirror/lib/codemirror.css" rel="stylesheet" >
<script src="/static/plugin/codemirror/lib/codemirror.js"></script>
<link href="/static/plugin/codemirror/theme/monokai.css" rel="stylesheet">
<link href="/static/plugin/codemirror/theme/idea.css" rel="stylesheet">
<link href="/static/plugin/codemirror/theme/eclipse.css" rel="stylesheet">
<link href="/static/plugin/codemirror/theme/rubyblue.css" rel="stylesheet">
<link href="/static/plugin/codemirror/theme/ambiance-mobile.css" rel="stylesheet">
<link href="/static/plugin/codemirror/theme/3024-day.css" rel="stylesheet">
<link href="/static/plugin/codemirror/theme/3024-night.css" rel="stylesheet">
<link href="/static/plugin/codemirror/theme/erlang-dark.css" rel="stylesheet">
<script src="/static/plugin/codemirror/mode/javascript/javascript.js"></script>
<script src="/static/plugin/codemirror/mode/python/python.js"></script>
<script src="/static/plugin/codemirror/mode/shell/shell.js"></script>
<script src="/static/plugin/codemirror/mode/php/php.js"></script>
<script src="/static/plugin/codemirror/mode/go/go.js"></script>
<style>
body {
background-color: #ffffff;
}
.footer {
padding-top: 5px;
padding-left: 10px;
text-align: left;
position: fixed;
bottom: 0px;
background-color:#ddd;
width:100%;
}
.footer > button{
border-radius: 25px;
}
.center{
margin-bottom: 60px;
}
/** {*/
/* padding: 2px;*/
/* margin: 2px;*/
/*}*/
/*.container {*/
/* height: 100vh;*/
/* width: 100%;*/
/* display: flex;*/
/* flex-direction: column;*/
/* justify-content: space-between;*/
/*}*/
/*.container .header {*/
/* display: flex;*/
/* align-items: flex-start;*/
/*}*/
/*.container .center {*/
/* flex: 1;*/
/* overflow: hidden;*/
/* display: flex;*/
/*}*/
/*.container .footer {*/
/* height: 50px;*/
/* display: flex;*/
/* align-items: flex-start;*/
/*}*/
</style>
</head>
<body>
<div class="layui-form layuimini-form layuimini-container layui-form-pane" lay-filter="scripts">
<div class="layui-form layuimini-form layuimini-container layui-form-pane container" lay-filter="scripts">
<!--<div class="layui-form layui-form-pane" lay-filter="scripts">-->
<div class="header">
<div class="layui-form-item" pane="">
<label class="layui-form-label required">脚本类型</label>
<div class="layui-input-block">
<input type="radio" name="script_code" id="script_code_sh" lay-filter="ck-code" value="shell" title="shell">
<input type="radio" name="script_code" id="script_code_php" lay-filter="ck-code" value="python" title="php">
<input type="radio" name="script_code" id="script_code_py" lay-filter="ck-code" value="python" title="python">
<input type="radio" name="script_code" id="script_code_js" lay-filter="ck-code" value="javascript" title="js" checked>
<input type="radio" name="script_code" id="script_code_jinja2" lay-filter="ck-code" value="jinja2" title="jinja2">
<input type="radio" name="script_code" id="script_code_sh" lay-filter="ck-code" value="shell" title="shell">
<input type="radio" name="script_code" id="script_code_go" lay-filter="ck-code" value="python" title="go">
</div>
</div>
@ -46,41 +102,52 @@
<select name="interest" lay-filter="select_theme" id="select_theme">
<option value=""></option>
<option value="default">default</option>
<option value="idea">idea</option>
<option value="eclipse">eclipse</option>
<option value="rubyblue">rubyblue</option>
<option value="ambiance-mobile">ambiance-mobile</option>
<option value="3024-day">3024-day</option>
<option value="3024-night">3024-night</option>
<option value="erlang-dark">erlang-dark</option>
<option value="monokai" selected>monokai</option>
</select>
</div>
</div>
</div>
<div class="center">
<div class="layui-form-item layui-form-text">
<label class="layui-form-label required">脚本区域</label>
<div class="layui-input-block">
<!--textarea-->
<textarea id="script_shell" style="display: none">#!/bin/sh
<textarea id="script_shell" class="hide" style="display: none">#!/bin/sh
</textarea>
<textarea id="script_python" class="hide" style="display: none">
#!/usr/bin/env python
# -*- coding: utf8 -*-
</textarea>
<textarea id="script_js" name='scripts_code' class="hide" style="display: none">
<textarea id="script_js" class="hide" style="display: none">
// javascript
function f(){
}</textarea>
<textarea id="script_code" name='scripts_code' class="hide" style="display: none">
</textarea>
</div>
</div>
</div>
<div class="layui-btn-container">
<div class="layui-btn-container footer">
<button class="layui-btn layui-btn-normal " lay-submit lay-filter="reBtn"><i class="layui-icon layui-icon-refresh"></i>刷新</button>
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn"><i class="layui-icon layui-icon-ok"></i>保存</button>
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="openRawBtn"><i class="layui-icon layui-icon-file-b"></i>查看原始文件</button>
</div>
</div>
<script>
const api_url = '/admin/view/{{name}}';
const api_save_url = '/admin/save_edit';
const api_save_url = '/admin/save_edit/{{name}}';
// 初始化 脚本编辑页面
function init_scripts(form) {
$.ajax({
@ -91,7 +158,9 @@ function f(){
// data:'',
// dataType:'json',
success: function(data) {
console.log(data);
// console.log(data);
editor.setValue(data);
form.render();
},error: function(XMLHttpRequest,textStatus,errorThrown) {
if (XMLHttpRequest.status == 0) {
layer.msg('Check Your Network.',{icon: 2},function () {});
@ -109,7 +178,7 @@ function f(){
}
</script>
<script>
var editor = CodeMirror.fromTextArea($("#script_js")[0], { //为你的textarea的ID号
var editor = CodeMirror.fromTextArea(document.getElementById("script_code"), { //为你的textarea的ID号 $("#script_code")[0]
lineNumbers: true,//是否显示行号
mode: "javascript", //默认语言
lineWrapping:true, //是否强制换行
@ -122,7 +191,8 @@ function f(){
indentWithTabs: true,
extraKeys: {"Ctrl-Space": "autocomplete"}//ctrl-space唤起智能提示
});
editor.setSize('auto','630px'); //设置宽度,高度
editor.setSize('auto','600px'); //设置宽度,高度
// editor.setSize('auto','auto'); //设置宽度,高度
//选择脚本类型JS
var script_sh=$("#script_shell").val();
@ -143,43 +213,26 @@ function f(){
});
//监听提交
form.on('submit(saveBtn)', function (data) {
alert(111)
return false
// let txt = editor.getValue();
let txt = editor.getValue();
// console.log(txt);
// let postData = {
// name:'{{name}}',
// // code:editor.getValue(),
// // code:editor.getValue().replaceAll("+","&").replaceAll("console.log","console.Log")
// }
let postData = {
name:'{{name}}',
code:txt,
// code:txt.replaceAll("+","&").replaceAll("console.log","console.Log")
}
// console.log(postData);
// $.ajax({
// type:'post',
// url:api_save_url,
// data:JSON.stringify(postData),
// dataType:'json',
// async:false,
// success:function (ret) {
// console.log(ret);
// // if(typeof (ret.ret)!="undefined" && ret.ret=="200"){
// // pstr = "params="+ret.msg+"&limit=1&page=1";
// // $.ajax({
// // type:'post',
// // url:api_url,
// // data:pstr,
// // async:false,
// // success:function (ret) {
// // // console.log(ret);
// // if(ret.ret == '200'){
// // layer.msg('脚本编辑成功');
// // }else {layer.msg(ret.msg);}
// // }
// // });
// // }
// }
// });
// return false;
$.ajax({
type:'post',
url:api_save_url,
data:postData,
dataType:'json',
async:false,
success:function (ret) {
console.log(ret);
layer.msg(ret.msg);
}
});
return false;
});
@ -192,6 +245,7 @@ function f(){
var txt=editor.getValue(); //editor.getValue()获取textarea中的值
var lang=$(this).prop("id");
// console.log(txt,lang);
console.log(data.value);
editor.setOption("mode",data.value);
switch (data.value) {
case 'shell':