rules.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # File : rules.py.py
  4. # Author: DaShenHan&道长-----先苦后甜,任凭晚风拂柳颜------
  5. # Date : 2022/8/25
  6. import json
  7. import os
  8. from time import time
  9. import js2py
  10. from quickjs import Function, Context
  11. from utils.log import logger
  12. # from utils.web import get_interval,UA
  13. from utils.ua import UA, get_interval
  14. from flask import render_template_string
  15. import ujson
  16. def getRuleLists():
  17. base_path = os.path.dirname(os.path.abspath(__file__)) # 当前文件所在目录
  18. # print(base_path)
  19. file_name = os.listdir(base_path)
  20. file_name = list(filter(lambda x: str(x).endswith('.js') and str(x).find('模板') < 0, file_name))
  21. # print(file_name)
  22. rule_list = [file.replace('.js', '') for file in file_name]
  23. # print(rule_list)
  24. return rule_list
  25. def getCacheCount():
  26. base_path = 'cache/' # 当前缓存js所在目录
  27. os.makedirs(base_path, exist_ok=True)
  28. file_name = os.listdir(base_path)
  29. file_name = list(filter(lambda x: str(x).endswith('.js') and str(x).find('模板') < 0, file_name))
  30. return len(file_name)
  31. def getRulesJs2py(path='cache', js_mode=0):
  32. t1 = time()
  33. base_path = path + '/' # 当前文件所在目录
  34. # print(base_path)
  35. os.makedirs(base_path, exist_ok=True)
  36. file_name = os.listdir(base_path)
  37. file_name = list(filter(lambda x: str(x).endswith('.js') and str(x).find('模板') < 0, file_name))
  38. # print(file_name)
  39. rule_list = [file.replace('.js', '') for file in file_name]
  40. js_path = [f'{path}/{rule}.js' for rule in rule_list]
  41. with open('js/模板.js', encoding='utf-8') as f:
  42. # before = f.read().split('export')[0]
  43. before = f.read().split('export default')[0]
  44. rule_codes = []
  45. # for js in js_path:
  46. # with open(js,encoding='utf-8') as f:
  47. # code = f.read()
  48. # rule_codes.append(js2py.eval_js(before+code))
  49. ctx = js2py.EvalJs()
  50. codes = []
  51. for i in range(len(js_path)):
  52. js = js_path[i]
  53. with open(js, encoding='utf-8') as f:
  54. code = f.read()
  55. new_code = 'var muban = JSON.parse(JSON.stringify(mubanDict));\n' + code.replace('rule', f'rule{i}', 1)
  56. # new_code = ''+code.replace('rule',f'rule{i}',1)
  57. codes.append(new_code)
  58. newCodes = before + '\n' + '\n'.join(codes)
  59. # print(newCodes)
  60. try:
  61. ctx.execute(newCodes)
  62. for i in range(len(js_path)):
  63. rule_codes.append(ctx.eval(f'rule{i}'))
  64. # print(type(rule_codes[0]),rule_codes[0])
  65. # print(rule_codes[0].title)
  66. # print(rule_codes[0].searchable)
  67. # print(rule_codes[0].quickSearch)
  68. # rule_codes 是个 js2py.base.JsObjectWrapper 类型,所以下面才能用. 获取属性
  69. new_rule_list = []
  70. for i in range(len(rule_list)):
  71. # 过滤排除drpy
  72. if js_mode == 1 and rule_list[i] == 'drpy':
  73. continue
  74. sable = rule_codes[i].searchable or 0
  75. tmpObj = {
  76. 'name': rule_list[i],
  77. # 'searchable':1 if (js_mode==1 and sable==2) else sable, # 对js模式1开放软件聚搜(还是算了,服务器遭不住)
  78. 'searchable': sable,
  79. 'quickSearch': rule_codes[i].quickSearch or 0,
  80. 'filterable': rule_codes[i].filterable or 0,
  81. }
  82. if rule_codes[i].multi:
  83. tmpObj['multi'] = 1
  84. new_rule_list.append(tmpObj)
  85. # print(new_rule_list)
  86. rules = {'list': new_rule_list, 'count': len(rule_list)}
  87. except Exception as e:
  88. logger.info(f'装载js内置源列表失败,置空内置源')
  89. rules = []
  90. logger.info(f'自动配置装载耗时:{get_interval(t1)}毫秒')
  91. return rules
  92. def getRules(path='cache', js_mode=0):
  93. t1 = time()
  94. base_path = path + '/' # 当前文件所在目录
  95. os.makedirs(base_path, exist_ok=True)
  96. file_name = os.listdir(base_path)
  97. file_name = list(filter(lambda x: str(x).endswith('.js') and str(x).find('模板') < 0, file_name))
  98. rule_list = [file.replace('.js', '') for file in file_name]
  99. js_path = [f'{path}/{rule}.js' for rule in rule_list]
  100. with open('js/模板.js', encoding='utf-8') as f:
  101. # before = f.read().split('export')[0]
  102. before = f.read().split('export default')[0]
  103. rule_codes = []
  104. ctx = Context()
  105. codes = []
  106. for i in range(len(js_path)):
  107. js = js_path[i]
  108. with open(js, encoding='utf-8') as f:
  109. code = f.read()
  110. new_code = 'var muban = JSON.parse(JSON.stringify(mubanDict));\n' + code.replace('var rule', f'var rule{i}',
  111. 1) + f'\nif (rule{i}.模板 && muban.hasOwnProperty(rule{i}.模板))' + '{' + f'rule{i} = Object.assign(muban[rule{i}.模板], rule{i});' + '}'
  112. # new_code = ''+code.replace('rule',f'rule{i}',1)
  113. codes.append(new_code)
  114. newCodes = before + '\n' + '\n'.join(codes)
  115. # print(newCodes)
  116. try:
  117. ctx.eval(newCodes)
  118. for i in range(len(js_path)):
  119. rule_codes.append(ctx.get(f'rule{i}'))
  120. # rule_codes 是个 js2py.base.JsObjectWrapper 类型,所以下面才能用. 获取属性
  121. new_rule_list = []
  122. for i in range(len(rule_list)):
  123. # 过滤排除drpy
  124. # if js_mode == 1 and rule_list[i] == 'drpy':
  125. # continue
  126. rule_codes[i] = ujson.loads(rule_codes[i].json())
  127. sable = rule_codes[i].get('searchable', 0)
  128. tmpObj = {
  129. 'name': rule_list[i],
  130. # 'searchable':1 if (js_mode==1 and sable==2) else sable, # 对js模式1开放软件聚搜(还是算了,服务器遭不住)
  131. 'searchable': sable,
  132. 'quickSearch': rule_codes[i].get('quickSearch', 0),
  133. 'filterable': rule_codes[i].get('filterable', 0),
  134. }
  135. # print(tmpObj)
  136. if rule_codes[i].get('multi'):
  137. tmpObj['multi'] = 1
  138. new_rule_list.append(tmpObj)
  139. # print(new_rule_list)
  140. rules = {'list': new_rule_list, 'count': len(rule_list)}
  141. except Exception as e:
  142. logger.info(f'装载js内置源列表失败,置空内置源并更新drpy_js_rule.js文件内容:{e}')
  143. with open('drpy_js_rule.js', mode='w+', encoding='utf-8') as f2:
  144. f2.write(newCodes)
  145. rules = {'list': [], 'count': 0}
  146. logger.info(f'自动配置装载耗时:{get_interval(t1)}毫秒')
  147. return rules
  148. def jxTxt2Json(text: str, host: str):
  149. try:
  150. data = render_template_string(text, host=host).strip().split('\n')
  151. except Exception as e:
  152. logger.info(f'jxTxt2Json发生错误:{e}')
  153. data = []
  154. jxs = []
  155. for i in data:
  156. i = i.strip()
  157. dt = i.split(',')
  158. if not i.startswith('#') and len(i) > 10:
  159. try:
  160. jxs.append({
  161. 'name': dt[0],
  162. 'url': dt[1],
  163. 'type': dt[2] if len(dt) > 2 and dt[2] else 0,
  164. 'ua': dt[3] if len(dt) > 3 and dt[3] else UA,
  165. })
  166. except Exception as e:
  167. logger.info(f'解析行有错误:{e}')
  168. return jxs
  169. def getJxs(path=None, host=None):
  170. custom_jx = 'base/解析.conf'
  171. if not os.path.exists(custom_jx):
  172. with open(custom_jx, 'w+', encoding='utf-8') as f1:
  173. msg = """# 这是用户自定义解析列表,不会被系统升级覆盖
  174. # 0123,对应,普通解析,json解析,并发多json解析,聚合解析,参数3不填默认0
  175. # flags是线路名称标识,会自动拦截并走以下的解析
  176. # 名称,链接,类型,ua (ua不填默认 Mozilla/5.0) 可以手动填 Dart/2.14 (dart:io)
  177. 虾米,https://dm.xmflv.com:4433/?url=
  178. """
  179. f1.write(msg)
  180. base_path = 'jiexi' # 自建解析目录
  181. if path is None:
  182. path = base_path
  183. os.makedirs(base_path, exist_ok=True)
  184. file_name = os.listdir(path)
  185. file_name = list(
  186. filter(lambda x: str(x).endswith('.js') and str(x).find('模板') < 0 and str(x).find('加密') < 0, file_name))
  187. # print(file_name)
  188. # jx_list = [file.replace('.js', '') for file in file_name]
  189. # print(file_name)
  190. # print(jx_list)
  191. # jx_str = '\n'.join([jx + ',{{host}}' + f'/parse/api/{jx}.js?url=,1' for jx in jx_list])
  192. # print(jx_str)
  193. jxs = []
  194. for file in file_name:
  195. ctx = Context()
  196. with open(os.path.join(base_path,file),encoding='utf-8') as f0:
  197. code = f0.read()
  198. try:
  199. ctx.eval(code)
  200. flag = ctx.get('flag')
  201. if flag:
  202. flag = flag.json()
  203. flag = ujson.loads(flag)
  204. if isinstance(flag,list) and len(flag) > 0:
  205. jx = file.replace('.js', '')
  206. logger.info(f'自建解析可用:{jx}')
  207. jxs.append({
  208. 'name': jx,
  209. 'url': f'{host}/parse/api/{jx}.js?url=',
  210. 'type': 1,
  211. 'ua': UA,
  212. 'flag': flag,
  213. })
  214. except Exception as e:
  215. logger.info(f'自建解析{file}写法有误:{e}')
  216. with open(f'{path}/解析.conf', encoding='utf-8') as f1:
  217. text = f1.read()
  218. # text = jx_str + '\n' + text
  219. jxs1 = jxTxt2Json(text, host)
  220. jxs.extend(jxs1)
  221. with open(custom_jx, encoding='utf-8') as f2:
  222. text = f2.read()
  223. jxs2 = jxTxt2Json(text, host)
  224. jxs.extend(jxs2)
  225. print(f'共计{len(jxs)}条解析')
  226. return jxs
  227. def getPys(path='txt/py'):
  228. t1 = time()
  229. base_path = os.path.dirname(os.path.abspath(os.path.dirname(__file__))) # 上级目录
  230. py_path = os.path.join(base_path, path)
  231. os.makedirs(py_path, exist_ok=True)
  232. file_name = os.listdir(py_path)
  233. file_name = list(filter(lambda x: str(x).endswith('.py'), file_name))
  234. # print(file_name)
  235. rule_list = [file.replace('.py', '') for file in file_name]
  236. py_path = [f'{path}/{rule}.py' for rule in rule_list]
  237. # print(py_path)
  238. new_rule_list = []
  239. for i in range(len(rule_list)):
  240. new_rule_list.append({
  241. 'name': rule_list[i],
  242. 'searchable': 1,
  243. 'quickSearch': 1,
  244. 'filterable': 0,
  245. })
  246. logger.info(f'自动加载Pyramid耗时:{get_interval(t1)}毫秒')
  247. return new_rule_list
  248. def gen_cache(path='txt/js/tg'):
  249. t1 = time()
  250. base_path = os.path.dirname(os.path.abspath(os.path.dirname(__file__))) # 上级目录
  251. py_path = os.path.join(base_path, path)
  252. os.makedirs(py_path, exist_ok=True)
  253. file_name = os.listdir(py_path)
  254. file_name = list(filter(lambda x: str(x).endswith('.js'), file_name))
  255. # print(file_name)
  256. rule_list = [file.replace('.js', '') for file in file_name]
  257. js_path = [f'{path}/{rule}.js' for rule in rule_list]
  258. new_rule_list = []
  259. for i in range(len(rule_list)):
  260. # print(js_path[i])
  261. rname = rule_list[i]
  262. new_rule_list.append(
  263. {
  264. "key": f"dr_{rname}",
  265. "name": f"{rname}(道长)",
  266. "type": 1,
  267. # "api": "{{host}}"+f"/vod?rule={rname}&ext="+"{{host}}/"+js_path[i],
  268. "api": "{{host}}" + f"/vod?rule={rname}&ext=" + js_path[i],
  269. "searchable": 2,
  270. "quickSearch": 0,
  271. "filterable": 0
  272. })
  273. logger.info(f'自动加载{len(new_rule_list)}个缓存JS耗时:{get_interval(t1)}毫秒')
  274. new_rules_texts = [json.dumps(new_rule, ensure_ascii=False) for new_rule in new_rule_list]
  275. # new_rules_text = json.dumps(new_rule_list,ensure_ascii=False)
  276. new_rules_text = ',\n'.join(new_rules_texts) + ','
  277. return new_rules_text
  278. if __name__ == '__main__':
  279. print(getRuleLists())
  280. # print(gen_cache())
  281. # print(gen_cache('txt/js/18'))
  282. custom_file = gen_cache() + '\n' + gen_cache('txt/js/18')
  283. print(custom_file)
  284. with open('custom.conf', 'w+', encoding='utf-8') as f:
  285. f.write(custom_file)