home.py 17.0 KB
Newer Older
H
hjdhnx 已提交
1 2 3 4 5 6
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File  : index.py
# Author: DaShenHan&道长-----先苦后甜,任凭晚风拂柳颜------
# Date  : 2022/9/6
import json
H
hjdhnx 已提交
7
import ujson
H
hjdhnx 已提交
8
import os
H
hjdhnx 已提交
9
import re
H
hjdhnx 已提交
10

H
hjdhnx 已提交
11
from flask import Blueprint,abort,render_template,render_template_string,url_for,redirect,make_response,send_from_directory,request
H
hjdhnx 已提交
12
from controllers.service import storage_service,rules_service,parse_service
H
hjdhnx 已提交
13
from controllers.classes import getClasses,getClassInfo
H
hjdhnx 已提交
14 15

from utils.files import getPics,custom_merge,getAlist,get_live_url,get_multi_rules,getCustonDict
H
hjdhnx 已提交
16
from js.rules import getRules,getPys
H
hjdhnx 已提交
17
from utils.encode import parseText,base64Encode,baseDecode
H
hjdhnx 已提交
18
from base.R import R
H
hjdhnx 已提交
19 20
from utils.system import getHost,is_linux
from utils.cfg import cfg
H
hjdhnx 已提交
21
from utils import parser
H
hjdhnx 已提交
22
from utils.ua import time,get_interval
H
hjdhnx 已提交
23
from utils.log import logger
H
hjdhnx 已提交
24
from utils.update import getLocalVer,getHotSuggest
H
hjdhnx 已提交
25 26
from js.rules import getJxs
import random
H
hjdhnx 已提交
27
from utils.web import getParmas
H
hjdhnx 已提交
28
import functools
H
hjdhnx 已提交
29

H
hjdhnx 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

home = Blueprint("home", __name__,static_folder='/static')

@home.route('/')
def forbidden():  # put application's code here
    abort(403)

@home.route('/favicon.ico')  # 设置icon
def favicon():
    # return home.send_static_file('img/favicon.svg')
    return redirect('/static/img/favicon.svg')
    # 对于当前文件所在路径,比如这里是static下的favicon.ico
    # return send_from_directory(os.path.join(app.root_path, 'static'),  'img/favicon.svg', mimetype='image/vnd.microsoft.icon')

@home.route('/index')
def index():
H
hjdhnx 已提交
46
    sup_port = cfg.get('SUP_PORT', 9001)
H
hjdhnx 已提交
47 48
    lsg = storage_service()
    pid_url = lsg.getItem('PID_URL')
H
hjdhnx 已提交
49 50
    manager0 = ':'.join(getHost(0).split(':')[0:2])
    manager1 = ':'.join(getHost(1).split(':')[0:2])
H
hjdhnx 已提交
51
    manager2 = pid_url or ':'.join(getHost(2).split(':')[0:2]).replace('https','http')
H
hjdhnx 已提交
52 53 54
    if sup_port:
        manager0 += f':{sup_port}'
        manager1 += f':{sup_port}'
H
hjdhnx 已提交
55 56 57
        if not pid_url:
            manager2 += f':{sup_port}'
    # print(manager2)
H
hjdhnx 已提交
58 59
    ver = getLocalVer()
    return render_template('index.html',ver=ver,getHost=getHost,manager0=manager0,manager1=manager1,manager2=manager2,is_linux=is_linux())
H
hjdhnx 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72 73

@home.route('/rules/clear')
def rules_to_clear():
    return render_template('rules_to_clear.html',rules=getRules(),classes=getClasses())

@home.route('/rules/view')
def rules_to_view():
    return render_template('rules_to_view.html',rules=getRules(),classes=getClasses())

@home.route('/pics')
def random_pics():
    id = getParmas('id')
    # print(f'id:{id}')
    pics = getPics()
H
hjdhnx 已提交
74
    # print(pics)
H
hjdhnx 已提交
75 76 77 78 79
    new_conf = cfg
    lsg = storage_service()
    store_conf_dict = lsg.getStoreConfDict()
    new_conf.update(store_conf_dict)
    if not new_conf.WALL_PAPER and len(pics) > 0:
H
hjdhnx 已提交
80 81 82 83 84 85 86 87 88
        if id and f'images/{id}.jpg' in pics:
            pic = f'images/{id}.jpg'
        else:
            pic = random.choice(pics)
        file = open(pic, "rb").read()
        response = make_response(file)
        response.headers['Content-Type'] = 'image/jpeg'
        return response
    else:
H
hjdhnx 已提交
89
        return redirect(new_conf.WALL_PAPER)
H
hjdhnx 已提交
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111

@home.route('/clear')
def clear_rule():
    rule = getParmas('rule')
    if not rule:
        return R.failed('规则字段必填')
    cache_path = os.path.abspath(f'cache/{rule}.js')
    if not os.path.exists(cache_path):
        return R.failed('服务端没有此规则的缓存文件!'+cache_path)
    os.remove(cache_path)
    return R.success('成功删除文件:'+cache_path)

@home.route("/plugin/<name>",methods=['GET'])
def plugin(name):
    # name=道长影视模板.js
    if not name or not name.split('.')[-1] in ['js','txt','py','json']:
        return R.failed(f'非法猥亵,未指定文件名。必须包含js|txt|json|py')
    try:
        return parser.toJs(name)
    except Exception as e:
        return R.failed(f'非法猥亵\n{e}')

H
hjdhnx 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
@home.route('/files/<name>')
def get_files(name):
    base_path = 'base/files'
    os.makedirs(base_path,exist_ok=True)
    file_path = os.path.join(base_path, f'{name}')
    if not os.path.exists(file_path):
        return R.failed(f'{file_path}文件不存在')

    with open(file_path, mode='rb') as f:
        file_byte = f.read()
    response = make_response(file_byte)
    filename = name
    response.headers['Content-Type'] = 'application/octet-stream'
    response.headers['Content-Disposition'] = f'attachment;filename="{filename}"'
    return response

H
hjdhnx 已提交
128
@home.route('/txt/<path:filename>')
H
hjdhnx 已提交
129
def custom_static_txt(filename):
H
hjdhnx 已提交
130 131 132 133
    # 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
    # print(filename)
    return send_from_directory('txt', filename)

H
hjdhnx 已提交
134 135 136 137 138 139
@home.route('/libs/<path:filename>')
def custom_static_libs(filename):
    # 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
    # print(filename)
    return send_from_directory('libs', filename)

H
hjdhnx 已提交
140 141 142 143 144 145 146 147 148 149 150 151 152
# @home.route('/txt/<name>')
# def get_txt_files(name):
#     base_path = 'txt'
#     os.makedirs(base_path,exist_ok=True)
#     file_path = os.path.join(base_path, f'{name}')
#     if not os.path.exists(file_path):
#         return R.failed(f'{file_path}文件不存在')
#
#     with open(file_path, mode='r',encoding='utf-8') as f:
#         file_byte = f.read()
#     response = make_response(file_byte)
#     response.headers['Content-Type'] = 'text/plain; charset=utf-8'
#     return response
H
hjdhnx 已提交
153

H
hjdhnx 已提交
154

H
hjdhnx 已提交
155 156
@home.route('/lives')
def get_lives():
H
hjdhnx 已提交
157 158 159
    # ?path=base/live.txt
    path = getParmas('path')
    live_path = path or 'base/直播.txt'
H
hjdhnx 已提交
160 161
    if not re.search('(txt|json|conf)$',live_path,re.M|re.S) or not re.search('^(txt|base)',live_path,re.M|re.S):
        abort(403)
H
hjdhnx 已提交
162
    if not os.path.exists(live_path):
H
hjdhnx 已提交
163 164 165
        # with open(live_path,mode='w+',encoding='utf-8') as f:
        #     f.write('')
        return ''
H
hjdhnx 已提交
166 167 168

    with open(live_path,encoding='utf-8') as f:
        live_text = f.read()
H
hjdhnx 已提交
169 170 171 172 173 174
    if len(live_text) > 100 and live_text.find('http') < 0:
        try:
            live_text = baseDecode(live_text)
            logger.info(f'{path} base64解码完毕')
        except:
            pass
H
hjdhnx 已提交
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
    response = make_response(live_text)
    response.headers['Content-Type'] = 'text/plain; charset=utf-8'
    return response

@home.route('/liveslib')
def get_liveslib():
    live_path = 'js/custom_spider.jar'
    if not os.path.exists(live_path):
        with open(live_path,mode='w+',encoding='utf-8') as f:
            f.write('')

    with open(live_path,mode='rb') as f:
        live_text = f.read()
    response = make_response(live_text)
    filename = 'custom_spider.jar'
    response.headers['Content-Type'] = 'application/octet-stream'
    response.headers['Content-Disposition'] = f'attachment;filename="{filename}"'
    return response

H
hjdhnx 已提交
194 195 196 197 198
@home.route('/hotsugg')
def get_hot_search():
    data = getHotSuggest()
    return R.success('获取成功',data)

H
hjdhnx 已提交
199 200 201 202 203 204 205 206 207
def merged_hide(merged_config):
    t1 = time()
    store_rule = rules_service()
    hide_rules = store_rule.getHideRules()
    hide_rule_names = list(map(lambda x: x['name'], hide_rules))
    # print(hide_rule_names)
    all_cnt = len(merged_config['sites'])

    def filter_show(x):
H
hjdhnx 已提交
208
        name = x['api'].split('rule=')[1].split('&')[0] if 'rule=' in x['api'] else x['key'].replace('dr_','')
H
hjdhnx 已提交
209 210 211 212 213 214
        # print(name)
        return name not in hide_rule_names

    merged_config['sites'] = list(filter(filter_show, merged_config['sites']))
    logger.info(f'数据库筛选隐藏规则耗时{get_interval(t1)}毫秒,共计{all_cnt}条规则,隐藏后可渲染{len(merged_config["sites"])}条规则')

H
hjdhnx 已提交
215 216 217
@home.route('/config/<int:mode>')
def config_render(mode):
    # print(dict(app.config))
H
hjdhnx 已提交
218
    tt = time()
H
hjdhnx 已提交
219 220 221
    UA = request.headers['User-Agent']
    ISTVB = 'okhttp/3' in UA
    logger.info(UA)
H
hjdhnx 已提交
222 223 224 225
    if mode == 1:
        jyw_ip = getHost(mode)
        logger.info(jyw_ip)
    new_conf = cfg
H
hjdhnx 已提交
226 227 228
    lsg = storage_service()
    store_conf_dict = lsg.getStoreConfDict()
    new_conf.update(store_conf_dict)
H
hjdhnx 已提交
229
    # print(new_conf)
H
hjdhnx 已提交
230
    # print(type(new_conf),new_conf)
H
hjdhnx 已提交
231
    host = getHost(mode)
232 233
    # ali_token = lsg.getItem('ALI_TOKEN')
    ali_token = new_conf.ALI_TOKEN
H
hjdhnx 已提交
234
    xr_mode = new_conf.XR_MODE
H
hjdhnx 已提交
235
    js_proxy = new_conf.JS_PROXY
H
hjdhnx 已提交
236
    js0_password = new_conf.JS0_PASSWORD
H
hjdhnx 已提交
237 238
    js_mode = int(new_conf.JS_MODE or 0)
    print(f'{type(js_mode)} jsmode:{js_mode}')
239
    # print(ali_token)
H
hjdhnx 已提交
240
    customConfig = getCustonDict(host,ali_token,js0_password)
H
hjdhnx 已提交
241
    # print(customConfig)
H
hjdhnx 已提交
242
    jxs = getJxs(host=host)
H
hjdhnx 已提交
243 244 245
    use_py = lsg.getItem('USE_PY')
    pys = getPys() if use_py else []
    # print(pys)
H
hjdhnx 已提交
246 247 248
    alists = getAlist()
    alists_str = json.dumps(alists, ensure_ascii=False)
    live_url = get_live_url(new_conf,mode)
H
hjdhnx 已提交
249
    rules = getRules('js',js_mode)
H
hjdhnx 已提交
250
    rules = get_multi_rules(rules)
H
hjdhnx 已提交
251
    # html = render_template('config.txt',rules=getRules('js'),host=host,mode=mode,jxs=jxs,base64Encode=base64Encode,config=new_conf)
H
hjdhnx 已提交
252
    html = render_template('config.txt',js0_password=js0_password,UA=UA,xr_mode=xr_mode,ISTVB=ISTVB,pys=pys,rules=rules,host=host,mode=mode,js_mode=js_mode,jxs=jxs,alists=alists,alists_str=alists_str,live_url=live_url,config=new_conf)
H
hjdhnx 已提交
253
    merged_config = custom_merge(parseText(html),customConfig)
H
hjdhnx 已提交
254 255
    # print(merged_config['sites'])
    merged_hide(merged_config)
H
hjdhnx 已提交
256
    # response = make_response(html)
H
hjdhnx 已提交
257
    # print(len(merged_config['sites']))
H
hjdhnx 已提交
258 259
    # print(merged_config['sites'])
    merged_config['sites'] = sort_sites_by_order(merged_config['sites'],js_mode)
H
hjdhnx 已提交
260 261 262 263
    # print(merged_config['parses'])
    parses = sort_parses_by_order(merged_config['parses'],host)
    # print(parses)
    merged_config['parses'] = parses
H
hjdhnx 已提交
264
    config_text = json.dumps(merged_config,ensure_ascii=False,indent=1)
H
hjdhnx 已提交
265 266 267 268 269 270 271 272 273 274

    # 依赖代理逻辑修改,改为admin/view去动态代理
    # if js_proxy:
    #     # print('js_proxy:',js_proxy)
    #     if '=>' in js_proxy:
    #         oldsrc = js_proxy.split('=>')[0]
    #         newsrc = js_proxy.split('=>')[1]
    #         print(f'js1源代理已启用,全局替换{oldsrc}为{newsrc}')
    #         config_text = config_text.replace(oldsrc,newsrc)

H
hjdhnx 已提交
275
    response = make_response(config_text)
H
hjdhnx 已提交
276
    # response = make_response(str(merged_config))
H
hjdhnx 已提交
277
    response.headers['Content-Type'] = 'application/json; charset=utf-8'
H
hjdhnx 已提交
278
    logger.info(f'自动生成动态配置共计耗时:{get_interval(tt)}毫秒')
H
hjdhnx 已提交
279 280
    return response

H
hjdhnx 已提交
281 282 283 284 285 286 287 288 289 290 291 292 293
def comp(x, y):
    if x['order'] > y['order']:
        return 1
    elif x['order'] < y['order']:
        return - 1
    else:
        if x['write_date'] < y['write_date']:
            return 1
        elif x['write_date'] > y['write_date']:
            return -1
        else:
            return 0

H
hjdhnx 已提交
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
def sort_sites_by_order(sites,js_mode=0):
    rules = rules_service()
    rule_list = rules.query_all()
    # print(rule_list)
    rule_names = list(map(lambda x: x['name'], rule_list))
    # print(rule_names)
    # print(sites)
    for i in range(len(sites)):
        # sites[i]['id'] = i+1
        site_name = sites[i]['api'].split('rule=')[1].split('&')[0] if 'rule=' in sites[i]['api'] else sites[i]['key']
        if js_mode and str(site_name).startswith('dr'):
            site_name = site_name.replace('dr_','')
        # print(site_name)
        if site_name in rule_names:
            site_rule = rule_list[rule_names.index(site_name)]
            sites[i]['state'] = 1 if site_rule['state'] is None else site_rule['state']
            sites[i]['order'] = 0 if site_rule['order'] is None else site_rule['order']
H
hjdhnx 已提交
311
            sites[i]['write_date'] = 0 if site_rule['write_date'] is None else site_rule['write_date'].timestamp()
H
hjdhnx 已提交
312 313 314
        else:
            sites[i]['state'] = 1
            sites[i]['order'] = 0
H
hjdhnx 已提交
315
            sites[i]['write_date'] = 0
H
hjdhnx 已提交
316 317
        # sites[i]['site_name'] = site_name
    # print(sites)
H
hjdhnx 已提交
318 319
    # sites.sort(key=lambda x: x['order'], reverse=False)
    sites.sort(key=functools.cmp_to_key(comp), reverse=False)
H
hjdhnx 已提交
320 321 322 323
    # print(sites)
    for site in sites:
        del site['state']
        del site['order']
H
hjdhnx 已提交
324
        del site['write_date']
H
hjdhnx 已提交
325 326
    return sites

H
hjdhnx 已提交
327 328 329 330 331 332
def sort_parses_by_order(parses,host):
    t1 = time()
    parse = parse_service()
    parse_list = parse.query_all()
    parse_url_list = list(map(lambda x: x['url'], parse_list))
    new_parses = []
H
hjdhnx 已提交
333
    new_parses_url = []
H
hjdhnx 已提交
334 335 336
    for i in range(len(parses)):
        # parses[i]['id'] = i + 1
        # 去重
H
hjdhnx 已提交
337 338
        if parses[i]['url'] in new_parses_url:
            # print(f"重复的解析:{parses[i]['name']},{parses[i]['url']}")
H
hjdhnx 已提交
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
            continue
        if str(parses[i]['url']).startswith(host):
            parses[i]['url'] = parses[i]['url'].replace(host,'')
        if parses[i]['url'] in parse_url_list:
            parse_rule = parse_list[parse_url_list.index(parses[i]['url'])]
            parses[i]['state'] = 1 if parse_rule['state'] is None else parse_rule['state']
            parses[i]['order'] = 0 if parse_rule['order'] is None else parse_rule['order']
            parses[i]['write_date'] = 0 if parse_rule['write_date'] is None else parse_rule['write_date'].timestamp()
        else:
            parses[i]['state'] = 1
            parses[i]['order'] = 0
            parses[i]['write_date'] = 0

        if not parses[i].get('header'):
            parses[i]['header'] = {'User-Agent': 'Mozilla/5.0'}
        if str(parses[i]['url']).startswith('/'):
            parses[i]['url'] = host + parses[i]['url']
        new_parses.append(parses[i])
H
hjdhnx 已提交
357
        new_parses_url.append(parses[i]['url'])
H
hjdhnx 已提交
358 359 360 361 362 363 364
    new_parses.sort(key=functools.cmp_to_key(comp), reverse=False)
    # print(sites)
    for par in new_parses:
        del par['state']
        del par['order']
        del par['write_date']
    # print(new_parses)
H
hjdhnx 已提交
365
    logger.info(f'{len(new_parses)}/{len(parses)}条解析解析排序耗时:{get_interval(t1)}毫秒')
H
hjdhnx 已提交
366 367
    return new_parses

H
hjdhnx 已提交
368 369 370 371 372
@home.route('/configs')
def config_gen():
    # 生成文件
    os.makedirs('txt',exist_ok=True)
    new_conf = cfg
H
hjdhnx 已提交
373 374 375
    lsg = storage_service()
    store_conf_dict = lsg.getStoreConfDict()
    new_conf.update(store_conf_dict)
H
hjdhnx 已提交
376 377
    try:
        use_py = lsg.getItem('USE_PY')
H
hjdhnx 已提交
378
        js_mode = int(new_conf.JS_MODE or 0)
H
hjdhnx 已提交
379
        js0_password = new_conf.JS0_PASSWORD
H
hjdhnx 已提交
380 381 382
        pys = getPys() if use_py else False
        alists = getAlist()
        alists_str = json.dumps(alists,ensure_ascii=False)
H
hjdhnx 已提交
383
        rules = getRules('js',js_mode)
H
hjdhnx 已提交
384
        rules = get_multi_rules(rules)
H
hjdhnx 已提交
385 386
        host0 = getHost(0)
        jxs = getJxs(host=host0)
H
hjdhnx 已提交
387
        set_local = render_template('config.txt',js0_password=js0_password,pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,0),mode=0,js_mode=js_mode,host=host0,jxs=jxs)
H
hjdhnx 已提交
388
        # print(set_local)
H
hjdhnx 已提交
389 390
        host1 = getHost(1)
        jxs = getJxs(host=host1)
H
hjdhnx 已提交
391
        set_area = render_template('config.txt',js0_password=js0_password,pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,1),mode=1,js_mode=js_mode,host=host1,jxs=jxs)
392 393
        host2 = getHost(2) or host1
        # print('远程地址:'+host2)
H
hjdhnx 已提交
394
        jxs = getJxs(host=host2)
H
hjdhnx 已提交
395
        set_online = render_template('config.txt',js0_password=js0_password,pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,2),mode=1,js_mode=js_mode,host=host2,jxs=jxs)
H
hjdhnx 已提交
396
        ali_token = new_conf.ALI_TOKEN
H
hjdhnx 已提交
397
        # parses = []
H
hjdhnx 已提交
398
        with open('txt/pycms0.json','w+',encoding='utf-8') as f:
H
hjdhnx 已提交
399
            customConfig = getCustonDict(host0,ali_token,js0_password)
H
hjdhnx 已提交
400
            set_dict = custom_merge(parseText(set_local), customConfig)
H
hjdhnx 已提交
401
            merged_hide(set_dict)
H
hjdhnx 已提交
402
            set_dict['sites'] = sort_sites_by_order(set_dict['sites'], js_mode)
H
hjdhnx 已提交
403 404 405 406 407
            # if not parses:
            #     print('生成静态配置时初始化排序parses')
            #     parses = sort_parses_by_order(set_dict['parses'])
            # set_dict['parses'] = parses
            set_dict['parses'] = sort_parses_by_order(set_dict['parses'],host0)
H
hjdhnx 已提交
408
            # set_dict = json.loads(set_local)
H
hjdhnx 已提交
409 410
            f.write(json.dumps(set_dict,ensure_ascii=False,indent=4))
        with open('txt/pycms1.json','w+',encoding='utf-8') as f:
H
hjdhnx 已提交
411
            customConfig = getCustonDict(host1,ali_token,js0_password)
H
hjdhnx 已提交
412
            set_dict = custom_merge(parseText(set_area), customConfig)
H
hjdhnx 已提交
413
            merged_hide(set_dict)
H
hjdhnx 已提交
414
            set_dict['sites'] = sort_sites_by_order(set_dict['sites'], js_mode)
H
hjdhnx 已提交
415
            set_dict['parses'] = sort_parses_by_order(set_dict['parses'],host1)
H
hjdhnx 已提交
416
            # set_dict = json.loads(set_area)
H
hjdhnx 已提交
417 418 419
            f.write(json.dumps(set_dict,ensure_ascii=False,indent=4))

        with open('txt/pycms2.json','w+',encoding='utf-8') as f:
H
hjdhnx 已提交
420
            customConfig = getCustonDict(host2,ali_token,js0_password)
H
hjdhnx 已提交
421
            set_dict = custom_merge(parseText(set_online), customConfig)
H
hjdhnx 已提交
422
            merged_hide(set_dict)
H
hjdhnx 已提交
423
            set_dict['sites'] = sort_sites_by_order(set_dict['sites'], js_mode)
H
hjdhnx 已提交
424
            set_dict['parses'] = sort_parses_by_order(set_dict['parses'],host2)
H
hjdhnx 已提交
425
            # set_dict = json.loads(set_online)
H
hjdhnx 已提交
426 427 428 429 430 431
            f.write(json.dumps(set_dict,ensure_ascii=False,indent=4))
        files = [os.path.abspath(rf'txt\pycms{i}.json') for i in range(3)]
        # print(files)
        return R.success('猫配置生成完毕,文件位置在:\n'+'\n'.join(files))
    except Exception as e:
        return R.failed(f'配置文件生成错误:\n{e}')
H
hjdhnx 已提交
432 433 434 435 436

@home.route("/info",methods=['get'])
def info_all():
    data = storage_service.query_all()
    return R.ok(data=data)