From 25978f94e75ddab31c0c14f5bb1d222b278dd2c0 Mon Sep 17 00:00:00 2001 From: Taois Date: Tue, 13 Jan 2026 13:29:26 +0800 Subject: [PATCH 001/101] =?UTF-8?q?fix:=20=E8=85=BE=E4=BA=91=E9=A9=BE?= =?UTF-8?q?=E9=9B=BE=E7=9A=84lazy=E9=80=82=E9=85=8D=E7=9A=AE=E5=8D=A1?= =?UTF-8?q?=E4=B8=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...05\276\344\272\221\351\251\276\351\233\276[\345\256\230].js" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/spider/js/\350\205\276\344\272\221\351\251\276\351\233\276[\345\256\230].js" "b/spider/js/\350\205\276\344\272\221\351\251\276\351\233\276[\345\256\230].js" index cdad280b..e45bce47 100644 --- "a/spider/js/\350\205\276\344\272\221\351\251\276\351\233\276[\345\256\230].js" +++ "b/spider/js/\350\205\276\344\272\221\351\251\276\351\233\276[\345\256\230].js" @@ -206,6 +206,6 @@ var rule = { }, lazy: async function () { let {input} = this; - return {parse: 1, jx: 1, url: input} + return {jx: 1, url: input} } } From 793b28fc1f24021430adc26344176f9bff003b7d Mon Sep 17 00:00:00 2001 From: Taois Date: Tue, 13 Jan 2026 13:36:31 +0800 Subject: [PATCH 002/101] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E5=93=94?= =?UTF-8?q?=E5=93=A9=E5=93=94=E5=93=A9=E7=9A=84siteKey?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../py/\345\223\224\345\223\251\345\223\224\345\223\251.py" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/spider/py/\345\223\224\345\223\251\345\223\224\345\223\251.py" "b/spider/py/\345\223\224\345\223\251\345\223\224\345\223\251.py" index 21dc932d..fbfb5782 100644 --- "a/spider/py/\345\223\224\345\223\251\345\223\224\345\223\251.py" +++ "b/spider/py/\345\223\224\345\223\251\345\223\224\345\223\251.py" @@ -499,7 +499,8 @@ def get_tuijian_filter(E): def __init__(self, query_params=None, t4_api=None): super().__init__(query_params=query_params, t4_api=t4_api) - self.localProxyUrl = self.getProxyUrl() + '&type=' + self.localProxyUrl = self.getProxyUrl() + '&siteType=3&siteKey=hipy_py_哔哩哔哩&type=' + print('localProxyUrl:', self.localProxyUrl) self.time_diff1 = {V: [0, 300], A0: [300, 900], AL: [900, 1800], AQ: [1800, 3600], '5': [3600, 0x4ee2d6d415b85acef80ffffffff]}; self.time_diff = L; From 7c9c843b28609c48e7325ebfa2b6981147a2de6e Mon Sep 17 00:00:00 2001 From: Taois Date: Tue, 13 Jan 2026 23:56:04 +0800 Subject: [PATCH 003/101] =?UTF-8?q?feat:=20=E5=B0=8F=E6=94=B9=E5=8A=A8?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 28 +- docs/other/HtmlParser.cs | 485 ++++++++++++++++++ docs/other/HtmlParser.java | 320 ++++++++++++ docs/other/htmlParser.ts | 349 +++++++++++++ docs/ruleDesc.md | 165 +++--- docs/updateRecord.md | 8 + jx/_30wmv.js | 1 + libs/drpyS.js | 3 +- public/index.html | 16 +- spider/catvod/TuneHub[B].js | 12 +- ...345\220\210\347\237\255\345\211\247[B].js" | 2 +- "spider/js/30wMV[\345\220\254].js" | 11 + ...24\345\223\251\345\223\224\345\223\251.py" | 24 +- utils/file.js | 21 +- 14 files changed, 1324 insertions(+), 121 deletions(-) create mode 100644 docs/other/HtmlParser.cs create mode 100644 docs/other/HtmlParser.java create mode 100644 docs/other/htmlParser.ts create mode 100644 jx/_30wmv.js diff --git a/README.md b/README.md index c122d8cf..aa98efd5 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ nodejs作为服务端的drpy实现。全面升级异步写法 ### 常用超链接 * [本项目主页-免翻](https://github.com/hjdhnx/drpy-node) -* [接口文档](docs/apidoc.md) | [接口列表如定时任务](docs/apiList.md) | [小猫影视-待对接T4](https://github.com/waifu-project/movie/pull/135) +* [接口文档](docs/apidoc.md) | [接口列表如定时任务](docs/apiList.md) | + ~~[小猫影视-待对接T4](https://github.com/waifu-project/movie/pull/135)~~ * [代码质量评估工具说明](docs/codeCheck.md) | [DS项目代码评估报告](docs/codeCheckReport.md) * [本地配置接口-动态本地](/config?healthy=1&pwd=$pwd) * [本地配置接口-动态外网/局域网](/config/1?healthy=1&pwd=$pwd) @@ -60,32 +61,17 @@ nodejs作为服务端的drpy实现。全面升级异步写法 * [酷9](https://wwbty.lanzouv.com/iGoUV3d3hxuf) * [千寻](https://wwbty.lanzouv.com/iSSN93d3hyzg) +* [皮卡丘](https://github.com/ingriddaleusag-dotcom/PeekPiliRelease) ## 更新记录 -### 20260112 - -更新至V1.3.15 - -### 20251017 - -更新至V1.3.14 - -### 20251015 +### 20260113 -更新至V1.3.13 +更新至V1.3.16 -### 20251014 - -更新至V1.3.12 - -### 20251013 - -更新至V1.3.11 - -### 20251012 +### 20260112 -更新至V1.3.10 +更新至V1.3.15 [点此查看完整更新记录](docs/updateRecord.md) diff --git a/docs/other/HtmlParser.cs b/docs/other/HtmlParser.cs new file mode 100644 index 00000000..2e2bc070 --- /dev/null +++ b/docs/other/HtmlParser.cs @@ -0,0 +1,485 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Net; +using System.Net.Http.Headers; +using System.Net.Security; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using System.Security.Cryptography.X509Certificates; +using System.Security.Policy; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Xml.Linq; +using Esprima.Ast; + +using Jint; +using Jint.Native; +using Jint.Runtime; +using Newtonsoft.Json.Linq; +using NSoup.Nodes; +using NSoup; +using NSoup.Select; +using Document = NSoup.Nodes.Document; +using RestSharp; +using System.Web; +using System.Net.Mime; +using Newtonsoft.Json; +using NSoup.Helper; +using System.Text.Encodings.Web; +using System.Buffers.Text; +using System.Text.Json.Nodes; + +namespace Peach.DataAccess +{ + //html解析器 + public class HtmlParser + { + RestClient client; + public HtmlParser() + { + ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true; + + var options = new RestClientOptions() + { + RemoteCertificateValidationCallback = (a, c, d, v) => true, + MaxTimeout = 100000, + ThrowOnAnyError = true, //设置不然不会报异常 + UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" + }; + client = new RestClient(options); + //client.AddDefaultHeader("Content-Type", "application/json"); + //client.AddDefaultHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"); + } + + /// + /// okhttp封装的html请求,给js调用http请求的 + /// + /// + /// + /// + public object Request(string url, JsValue arguments) + { + Uri uri = new Uri(url); + string Host = uri.Host; + var method = arguments.AsObject()["method"]?.ToString(); + var _headers = arguments.AsObject()["headers"].AsObject(); + var Referer = _headers["Referer"]?.ToString(); + var UserAgent = _headers["User-Agent"]?.ToString(); + var Cookie = _headers["Cookie"]?.ToString(); + var ContentType = _headers["Content-Type"]?.ToString(); + + var Data = arguments.AsObject()["data"]?.ToString(); + var Body = arguments.AsObject()["body"]?.ToString(); + + var Buffer = arguments.AsObject()["buffer"]?.ToString(); + + + + String charset = "utf-8"; + if (ContentType != null && ContentType.Split("charset=").Length > 1) + { + charset = ContentType.Split("charset=")[1]; + } + + var request = new RestRequest(url); + + if (!string.IsNullOrEmpty(Data) && !Data.Equals("undefined")) + { + // 序列化JSON数据 + string post_data = JsonConvert.SerializeObject(Data); + // 将JSON参数添加至请求中 + request.AddParameter("application/json", post_data, ParameterType.RequestBody); + + } + + if (!string.IsNullOrEmpty(Body) && !Body.Equals("undefined")) + { + String[] queryS = Body.Split("&"); + foreach (String query in queryS) + { + //String query = queryS[i]; + int tmp = query.IndexOf("="); + String key; + String value; + if (tmp != -1) + { + key = query.Substring(0, tmp); + value = query[(tmp + 1)..]; + } + else + { + key = query; + value = ""; + } + request.AddParameter(key, value); + } + } + + if (string.IsNullOrEmpty(UserAgent)) + UserAgent = "Mozilla/5.0 (Linux; Android 11; M2007J3SC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045714 Mobile Safari/537.36"; + request.AddHeader("User-Agent", UserAgent); + if (!string.IsNullOrEmpty(Referer)) + request.AddHeader("Referer", Referer); + + if (!string.IsNullOrEmpty(Cookie) && !Cookie.Equals("undefined")) + { + client.AddDefaultHeader("Cookie", Cookie); + } + string rContent = ""; + JsObject header = new (_headers.Engine); + + try + { + var client = new RestClient(url); + + RestResponse? response; + if (method?.ToLower() == "post") + response = client.Post(request); + else + response = client.Get(request); + + //rContent = response.Content; + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + rContent = HttpUtility.UrlDecode(response.RawBytes == null ? Array.Empty() : response.RawBytes, + Encoding.GetEncoding(charset)); + + if (response.Headers != null) + { + foreach (var item in response.Headers) + { + header.Set(item.Name, item.Value == null ? "" : item.Value.ToString()); + } + } + + if (Buffer == "1") + { + return new { headers = header, content = response.RawBytes }; + } + else if (Buffer == "2") + { + return new { headers = header, content = Convert.ToBase64String(Encoding.UTF8.GetBytes(rContent)) }; + } + else + { + return new { headers = header, content = rContent }; + } + } + catch (Exception) + { } + return new { headers = header, content = "" }; + } + + private static readonly Regex p = new ("url\\((.*?)\\)", RegexOptions.Multiline | RegexOptions.Singleline); + private static readonly Regex NOAdd_INDEX = new (":eq|:lt|:gt|:first|:last|^body$|^#"); + private static readonly Regex URLJOIN_ATTR = new ("(url|src|href|-original|-src|-play|-url|style)$|^(data-|url-|src-)", RegexOptions.Multiline | RegexOptions.IgnoreCase); + private static readonly Regex SPECIAL_URL = new ("^(ftp|magnet|thunder|ws):", RegexOptions.Multiline | RegexOptions.IgnoreCase); + private static String pdfh_html = ""; + private static String pdfa_html = ""; + private static Document? pdfh_doc = null; + private static Document? pdfa_doc = null; + + public static string JoinUrl(string parent, string child) + { + if (string.IsNullOrWhiteSpace(parent)) + { + return child; + } + + Uri url; + string q = parent; + try + { + url = new Uri(new Uri(parent), child); + q = url.ToString(); + } + catch (Exception) + { + //e.printStackTrace(); + } + // if (q.Contains("#")) { + // q = q.ReplaceAll("^(.+?)#.*?$", "$1"); + // } + return q; + } + + public class Painfo + { + public string? nparse_rule; + public int nparse_index; + public List? excludes; + } + + private static Painfo GetParseInfo(string nparse) + { + /* + 根据传入的单规则获取 parse规则,索引位置,排除列表 -- 可以用于剔除元素,支持多个,按标签剔除,按id剔除等操作 + :param nparse: + :return:*/ + Painfo painfo = new Painfo(); + //List excludes = new ArrayList<>(); //定义排除列表默认值为空 + //int nparse_index; //定义位置索引默认值为0 + painfo.nparse_rule = nparse; //定义规则默认值为本身 + if (nparse.Contains(":eq")) + { + painfo.nparse_rule = nparse.Split(":")[0]; + string nparse_pos = nparse.Split(":")[1]; + + if (painfo.nparse_rule.Contains("--")) + { + string[] rules = painfo.nparse_rule.Split("--"); + painfo.excludes = rules.ToList();// new(Arrays.asList(rules)); + painfo.excludes.RemoveAt(0); + painfo.nparse_rule = rules[0]; + } + else if (nparse_pos.Contains("--")) + { + string[] rules = nparse_pos.Split("--"); + painfo.excludes = rules.ToList();// new ArrayList<>(Arrays.asList(rules)); + painfo.excludes.RemoveAt(0); + nparse_pos = rules[0]; + } + + try + { + painfo.nparse_index = int.Parse(nparse_pos.Replace("eq(", "").Replace(")", "")); + } + catch (Exception) + { + painfo.nparse_index = 0; + } + } + else + { + if (nparse.Contains("--")) + { + string[] rules = painfo.nparse_rule.Split("--"); + painfo.excludes = rules.ToList();// new ArrayList<>(Arrays.asList(rules)); + painfo.excludes.RemoveAt(0); + painfo.nparse_rule = rules[0]; + } + } + return painfo; + } + + //pdfh + public string ParseDomForUrl(string html, string rule) + { + return ParseDom(html, rule, ""); + + } + //pd + public string ParseDom(string html, string rule, string Add_url) + { + if (string.IsNullOrWhiteSpace(html)) return ""; + if (!pdfh_html.Equals(html)) + { + pdfh_html = html; + pdfh_doc = NSoupClient.Parse(html); + } + Document? doc = pdfh_doc; + //Document doc = NSoupClient.Parse(html); + if (rule.Equals("body&&Text") || rule.Equals("Text")) + return doc.Text(); + else if (rule.Equals("body&&Html") || rule.Equals("Html")) + return doc.Html(); + + string option = ""; + if (rule.Contains("&&")) + { + string[] rs = rule.Split("&&"); + option = rs[rs.Length - 1]; + List excludes = rs.ToList();// new ArrayList<>(Arrays.asList(rs)); + excludes.RemoveAt(rs.Length - 1); + rule = string.Join("&&", excludes);// TextUtils.join("&&", excludes); + } + rule = parseHikerToJq(rule, true); + string[]? parses = rule.Split(" "); + Elements ret = new (); + foreach (string nparse in parses) + { + ret = parseOneRule(doc, nparse, ret); + if (ret.IsEmpty || ret.Count <= 0) return ""; + } + if (string.IsNullOrWhiteSpace(option)) + return ret.OuterHtml(); + if (option.Equals("Text")) + return ret.First.Text(); + else if (option.Equals("Html")) + return ret.Html(); + else //(JSUtils.isNotEmpty(option)) + { + string? result = ret.Attr(option); + if (option.ToLower().Contains("style") && result.Contains("url(")) + { + Match m = p.Match(result); + if (m.Success) + result = m.Groups[1]?.Value; + result = Regex.Replace(result, "^['|\"](.*)['|\"]$", "$1"); + } + if (!string.IsNullOrWhiteSpace(result) && !string.IsNullOrWhiteSpace(Add_url))// (JSUtils.isNotEmpty(result) && JSUtils.isNotEmpty(Add_url)) + { + // 需要自动urljoin的属性 + Match m = URLJOIN_ATTR.Match(option); + Match n = SPECIAL_URL.Match(result); + //if (isUrl(option)) { + if (m.Success && !n.Success) + { + if (result.Contains("http")) + result = result[result.IndexOf("http")..]; + else + result = JoinUrl(Add_url, result); + } + } + return result; + } + + } + //pdfa + public String[] ParseDomForArray(string html, string rule) + { + if (!pdfa_html.Equals(html)) + { + pdfa_html = html; + pdfa_doc = NSoupClient.Parse(html); + } + Document? doc = pdfa_doc; + List? eleHtml = new(); + //Document doc = NSoupClient.Parse(html); + + rule = parseHikerToJq(rule, false); + string[]? parses = rule.Split(" "); + Elements ret = new (); + foreach (var pars in parses) + { + ret = parseOneRule(doc, pars, ret); + if (ret.IsEmpty) return eleHtml.ToArray(); + } + foreach (Element it in ret) + { + eleHtml.Add(it.OuterHtml()); + } + + return eleHtml.ToArray(); + } + //pdfl + public String[] ParseDomForList(string html, string rule, string list_text, string list_url, string urlKey) + { + if (!pdfa_html.Equals(html)) + { + pdfa_html = html; + pdfa_doc = NSoupClient.Parse(html); + } + Document? doc = pdfa_doc; + //Document doc = NSoupClient.Parse(html); + List? new_vod_list = new(); + + rule = parseHikerToJq(rule, false); + string[]? parses = rule.Split(" "); + Elements ret = new (); + + foreach (string pars in parses) + { + ret = parseOneRule(doc, pars, ret); + if (ret.IsEmpty) return new_vod_list.ToArray(); + } + + foreach (Element it in ret) + { + new_vod_list.Add(ParseDom(it.OuterHtml(), list_text, "").Trim() + '$' + ParseDom(it.OuterHtml(), list_url, urlKey)); + } + + return new_vod_list.ToArray(); + } + + + + private string parseHikerToJq(string parse, bool first) + { + /* + 海阔解析表达式转原生表达式,自动补eq,如果传了first就最后一个也取eq(0) + :param parse: + :param first: + :return: + */ + // 不自动加eq下标索引 + if (parse.Contains("&&")) + { + string[]? parses = parse.Split("&&"); //带&&的重新拼接 + List? new_parses = new(); //构造新的解析表达式列表 + for (int i = 0; i < parses.Length; i++) + { + string[]? pss = parses[i].Split(" "); + string? ps = pss[pss.Length - 1]; //如果分割&&后带空格就取最后一个元素 + Match? m = NOAdd_INDEX.Match(ps); // Matcher m = NOAdd_INDEX.matcher(ps); + //if (!isIndex(ps)) { + if (!m.Success) + { + if (!first && i >= parses.Length - 1) + { //不传first且遇到最后一个,不用补eq(0) + new_parses.Add(parses[i]); + } + else + { + new_parses.Add(parses[i] + ":eq(0)"); + } + } + else + { + new_parses.Add(parses[i]); + } + } + parse = string.Join(" ", new_parses);// TextUtils.join(" ", new_parses); + } + else + { + string[]? pss = parse.Split(" "); + string? ps = pss[pss.Length - 1]; //如果分割&&后带空格就取最后一个元素 + //Matcher m = NOAdd_INDEX.matcher(ps); + Match? m = NOAdd_INDEX.Match(ps); + //if (!isIndex(ps) && first) { + if (!m.Success && first) + { + parse += ":eq(0)"; + } + } + return parse; + } + + private Elements parseOneRule(Document doc, string parse, Elements ret) + { + Painfo? info = GetParseInfo(parse); + if (ret.IsEmpty) + { + ret = doc.Select(info.nparse_rule); + } + else + { + ret = ret.Select(info.nparse_rule); + } + if (parse.Contains(":eq")) + { + if (info.nparse_index < 0) + { + ret = ret.Eq(ret.Count + info.nparse_index); + } + else + { + ret = ret.Eq(info.nparse_index); + } + } + + if (info.excludes != null && !ret.IsEmpty) + { + foreach (var exclude in info.excludes) + { + ret.Select(exclude).Remove(); + } + } + return ret; + } + } +} diff --git a/docs/other/HtmlParser.java b/docs/other/HtmlParser.java new file mode 100644 index 00000000..bdad1e83 --- /dev/null +++ b/docs/other/HtmlParser.java @@ -0,0 +1,320 @@ +package com; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class HtmlParser { + private static String pdfh_html = ""; + private static String pdfa_html = ""; + private static final Pattern p = Pattern.compile("url\\((.*?)\\)", Pattern.MULTILINE | Pattern.DOTALL); + private static final Pattern NOADD_INDEX = Pattern + .compile(":eq|:lt|:gt|:first|:last|:not|:even|:odd|:has|:contains|:matches|:empty|^body$|^#"); // 不自动加eq下标索引 + private static final Pattern URLJOIN_ATTR = Pattern.compile("(url|src|href|-original|-src|-play|-url|style)$|^(data-|url-|src-)", + Pattern.MULTILINE | Pattern.CASE_INSENSITIVE); // 需要自动urljoin的属性 + private static final Pattern SPECIAL_URL = Pattern.compile("^(ftp|magnet|thunder|ws):", + Pattern.MULTILINE | Pattern.CASE_INSENSITIVE); // 过滤特殊链接,不走urlJoin + private static Document pdfh_doc = null; + private static Document pdfa_doc = null; + + public static String join(CharSequence delimiter, @SuppressWarnings("rawtypes") Iterable tokens) { + final Iterator it = tokens.iterator(); + if (!it.hasNext()) { + return ""; + } + final StringBuilder sb = new StringBuilder(); + sb.append(it.next()); + while (it.hasNext()) { + sb.append(delimiter); + sb.append(it.next()); + } + return sb.toString(); + } + + public static String join(CharSequence delimiter, Object[] tokens) { + final int length = tokens.length; + if (length == 0) { + return ""; + } + final StringBuilder sb = new StringBuilder(); + sb.append(tokens[0]); + for (int i = 1; i < length; i++) { + sb.append(delimiter); + sb.append(tokens[i]); + } + return sb.toString(); + } + + public static String joinUrl(String parent, String child) { + if (parent.isEmpty()) { + return child; + } + + URL url; + String q = parent; + try { + url = new URL(new URL(parent), child); + q = url.toExternalForm(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + // if (q.contains("#")) { + // q = q.replaceAll("^(.+?)#.*?$", "$1"); + // } + return q; + } + + public static class Painfo { + public String nparse_rule; + public int nparse_index; + public List excludes; + } + + private static Painfo getParseInfo(String nparse) { + /* + * 根据传入的单规则获取 parse规则,索引位置,排除列表 -- 可以用于剔除元素,支持多个,按标签剔除,按id剔除等操作 :param nparse: + * :return: + */ + Painfo painfo = new Painfo(); + // List excludes = new ArrayList<>(); //定义排除列表默认值为空 + // int nparse_index; //定义位置索引默认值为0 + painfo.nparse_rule = nparse; // 定义规则默认值为本身 + if (nparse.contains(":eq")) { + painfo.nparse_rule = nparse.split(":")[0]; + String nparse_pos = nparse.split(":")[1]; + + if (painfo.nparse_rule.contains("--")) { + String[] rules = painfo.nparse_rule.split("--"); + painfo.excludes = new ArrayList<>(Arrays.asList(rules)); + painfo.excludes.remove(0); + painfo.nparse_rule = rules[0]; + } else if (nparse_pos.contains("--")) { + String[] rules = nparse_pos.split("--"); + painfo.excludes = new ArrayList<>(Arrays.asList(rules)); + painfo.excludes.remove(0); + nparse_pos = rules[0]; + } + + try { + painfo.nparse_index = Integer.parseInt(nparse_pos.replace("eq(", "").replace(")", "")); + } catch (Exception e1) { + painfo.nparse_index = 0; + } + } else { + if (nparse.contains("--")) { + String[] rules = painfo.nparse_rule.split("--"); + painfo.excludes = new ArrayList<>(Arrays.asList(rules)); + painfo.excludes.remove(0); + painfo.nparse_rule = rules[0]; + } + } + return painfo; + } + + private static String parseHikerToJq(String parse, boolean first) { + /* + * 海阔解析表达式转原生表达式,自动补eq,如果传了first就最后一个也取eq(0) :param parse: :param first: + * :return: + */ + // 不自动加eq下标索引 + if (parse.contains("&&")) { + String[] parses = parse.split("&&"); // 带&&的重新拼接 + List new_parses = new ArrayList<>(); // 构造新的解析表达式列表 + for (int i = 0; i < parses.length; i++) { + String[] pss = parses[i].split(" "); + String ps = pss[pss.length - 1]; // 如果分割&&后带空格就取最后一个元素 + Matcher m = NOADD_INDEX.matcher(ps); + if (!m.find()) { + if (!first && i >= parses.length - 1) { // 不传first且遇到最后一个,不用补eq(0) + new_parses.add(parses[i]); + } else { + new_parses.add(parses[i] + ":eq(0)"); + } + } else { + new_parses.add(parses[i]); + } + } + parse = join(" ", new_parses); + } else { + String[] pss = parse.split(" "); + String ps = pss[pss.length - 1]; // 如果分割&&后带空格就取最后一个元素 + Matcher m = NOADD_INDEX.matcher(ps); + if (!m.find() && first) { + parse = parse + ":eq(0)"; + } + } + return parse; + } + + public static String parseDomForUrl(String html, String rule, String add_url) { + if (!pdfh_html.equals(html)) { + pdfh_html = html; + pdfh_doc = Jsoup.parse(html); + } + Document doc = pdfh_doc; + if (rule.equals("body&&Text") || rule.equals("Text")) { + return doc.text(); + } else if (rule.equals("body&&Html") || rule.equals("Html")) { + return doc.html(); + } + String option = ""; + if (rule.contains("&&")) { + String[] rs = rule.split("&&"); + option = rs[rs.length - 1]; + List excludes = new ArrayList<>(Arrays.asList(rs)); + excludes.remove(rs.length - 1); + rule = join("&&", excludes); + } + rule = parseHikerToJq(rule, true); + String[] parses = rule.split(" "); + Elements ret = new Elements(); + for (String nparse : parses) { + ret = parseOneRule(doc, nparse, ret); + if (ret.isEmpty()) { + return ""; + } + } + String result = null; + if (!option.isEmpty()) { + if (option.equals("Text")) { + result = ret.text(); + } else if (option.equals("Html")) { + result = ret.html(); + } else { + String[] options = option.split("[||]"); + for (String opt : options) { + result = ret.attr(opt); + + if (opt.toLowerCase().contains("style") && result.contains("url(")) { + Matcher m = p.matcher(result); + if (m.find()) { + result = m.group(1); + } + // 2023/07/28新增 style取内部链接自动去除首尾单双引号 + result = result.replaceAll("^['|\"](.*)['|\"]$", "$1"); + } + if (!result.isEmpty() && !add_url.isEmpty()) { + // 需要自动urljoin的属性 + Matcher m = URLJOIN_ATTR.matcher(opt); + Matcher n = SPECIAL_URL.matcher(result); + if (m.find() && !n.find()) { + if (result.contains("http")) { + result = result.substring(result.indexOf("http")); + } else { + result = joinUrl(add_url, result); + } + } + } + if (!result.isEmpty()) { + return result; + } + } + } + + } else { + result = ret.outerHtml(); + } + return result; + + } + + public static List parseDomForArray(String html, String rule) { + if (!pdfa_html.equals(html)) { + pdfa_html = html; + pdfa_doc = Jsoup.parse(html); + } + Document doc = pdfa_doc; + rule = parseHikerToJq(rule, false); + String[] parses = rule.split(" "); + Elements ret = new Elements(); + for (String pars : parses) { + ret = parseOneRule(doc, pars, ret); + if (ret.isEmpty()) { + return new ArrayList<>(); + } + } + + List eleHtml = new ArrayList<>(); + for (int i = 0; i < ret.size(); i++) { + Element element1 = ret.get(i); + eleHtml.add(element1.outerHtml()); + } + return eleHtml; + } + + private static Elements parseOneRule(Document doc, String nparse, Elements ret) { + Painfo painfo = getParseInfo(nparse); + if (ret.isEmpty()) { + ret = doc.select(painfo.nparse_rule); + } else { + ret = ret.select(painfo.nparse_rule); + } + + if (nparse.contains(":eq")) { + if (painfo.nparse_index < 0) { + ret = ret.eq(ret.size() + painfo.nparse_index); + } else { + ret = ret.eq(painfo.nparse_index); + } + } + + if (painfo.excludes != null && !ret.isEmpty()) { + ret = ret.clone(); // 克隆一个, 免得直接remove会影响doc的缓存 + for (int i = 0; i < painfo.excludes.size(); i++) { + ret.select(painfo.excludes.get(i)).remove(); + } + } + return ret; + } + + public static List parseDomForList(String html, String p1, String list_text, String list_url, + String add_url) { + if (!pdfa_html.equals(html)) { + pdfa_html = html; + pdfa_doc = Jsoup.parse(html); + } + Document doc = pdfa_doc; + p1 = parseHikerToJq(p1, false); + String[] parses = p1.split(" "); + Elements ret = new Elements(); + for (String pars : parses) { + ret = parseOneRule(doc, pars, ret); + if (ret.isEmpty()) { + return new ArrayList<>(); + } + } + List new_vod_list = new ArrayList<>(); + for (int i = 0; i < ret.size(); i++) { + String it = ret.get(i).outerHtml(); + new_vod_list.add(parseDomForUrl(it, list_text, "").trim() + '$' + parseDomForUrl(it, list_url, add_url)); + } + return new_vod_list; + } + + public static void main(String[] args) { + XLHttpUtils.Request url = new XLHttpUtils.Request().get().url("https://m.yskanba.com/b-ertu.html"); + String string = url.exec().body().string(); + System.out.println(string); + String html = string; + String rule = ".posterPic&&img&&data-original||src"; + String ret = HtmlParser.parseDomForUrl(html, rule, ""); + System.out.println(ret); + rule = ".tabt3&&span:not(:contains(云播tk))"; + List rets = HtmlParser.parseDomForArray(html, rule); + System.out.println(rets); + rule = ".tabt3 span:not(:matches(云播tk))"; + rets = HtmlParser.parseDomForArray(html, rule); + System.out.println(rets); + } +} diff --git a/docs/other/htmlParser.ts b/docs/other/htmlParser.ts new file mode 100644 index 00000000..47c9814f --- /dev/null +++ b/docs/other/htmlParser.ts @@ -0,0 +1,349 @@ +/*! + * @module htmlParser + * @brief T3解析html处理库 + * @version 3.1.0 + * + * @original-author hjdhnx + * @original-source {@link https://github.com/hjdhnx/hipy-server/blob/master/app/t4/base/htmlParser.py | Source on GitHub} + * + * @modified-by HiramWong + * @modification-date 2023-04-09T18:31:59+08:00 + * @modification-description Python转TypeScript, 适用于JavaScript项目 + */ + +import * as cheerio from 'cheerio'; +import jsonpath from 'jsonpath'; +import urlJoin from 'url'; + +const PARSE_CACHE = true; // 解析缓存 +const NOADD_INDEX = ':eq|:lt|:gt|:first|:last|:not|:even|:odd|:has|:contains|:matches|:empty|^body$|^#'; // 不自动加eq下标索引 +const URLJOIN_ATTR = '(url|src|href|-original|-src|-play|-url|style)$|^(data-|url-|src-)'; // 需要自动urljoin的属性 +const SPECIAL_URL = '^(ftp|magnet|thunder|ws):'; // 过滤特殊链接,不走urlJoin + +class Jsoup { + MY_URL: string = ''; + pdfh_html = ''; + pdfa_html = ''; + + pdfh_doc = null; + pdfa_doc: cheerio.Root | null = null; + + // 构造函数 + constructor(MY_URL: string = '') { + this.MY_URL = MY_URL; + } + + // 测试 + test(text: string, string: string): boolean { + const searchObj = new RegExp(text, 'mi').exec(string); + return searchObj ? true : false; + } + + // 包含 + contains(text: string, match: string): boolean { + return text.indexOf(match) !== -1; + } + + /** + * 海阔解析表达式转原生表达式,自动补eq,如果传了first就最后一个也取eq(0) + * @param parse: 解析表达式 + * @param first: 是否第一个 + * @returns {string} + */ + parseHikerToJq(parse: string, first: boolean = false): string { + if (this.contains(parse, '&&')) { + const parses = parse.split('&&'); // 带&&的重新拼接 + let new_parses: string[] = []; // 构造新的解析表达式列表 + for (let i = 0; i < parses.length; i++) { + const ps_list = parses[i].split(' '); + const ps = ps_list[ps_list.length - 1]; // 如果分割&&后带空格就取最后一个元素 + if (!this.test(NOADD_INDEX, ps)) { + if (!first && i >= parses.length - 1) { + // 不传first且遇到最后一个,不用补eq(0) + new_parses.push(parses[i]); + } else { + new_parses.push(`${parses[i]}:eq(0)`); + } + } else { + new_parses.push(parses[i]); + } + } + parse = new_parses.join(' '); + } else { + const ps_list = parse.split(' '); + const ps = ps_list[ps_list.length - 1]; // 如果带空格就取最后一个元素 + if (!this.test(NOADD_INDEX, ps) && first) { + parse = `${parse}:eq(0)`; + } + } + + return parse; + } + + /** + * 根据传入的单规则获取 parse规则, 索引位置,排除列表 -- 可以用于剔除元素,支持多个, 按标签剔除, 按id剔除等操作 + * @param nparse + * @returns {rule: string, index: number, excludes: string[]} + */ + getParseInfo(nparse: string): { nparse_rule: string; nparse_index: number; excludes: string[] } { + let excludes: string[] = []; // 定义排除列表默认值为空 + let nparse_index: number = 0; // 定义位置索引默认值为0 + let nparse_rule: string = nparse; // 定义规则默认值为本身 + + if (this.contains(nparse, ':eq')) { + nparse_rule = nparse.split(':eq')[0]; + let nparse_pos = nparse.split(':eq')[1]; + if (this.contains(nparse_rule, '--')) { + excludes = nparse_rule.split('--').slice(1); + nparse_rule = nparse_rule.split('--')[0]; + } else if (this.contains(nparse_pos, '--')) { + excludes = nparse_pos.split('--').slice(1); + nparse_pos = nparse_pos.split('--')[0]; + } + try { + nparse_index = parseInt(nparse_pos.split('(')[1].split(')')[0]); + } catch { + } + } else if (this.contains(nparse, '--')) { + nparse_rule = nparse.split('--')[0]; + excludes = nparse.split('--').slice(1); + } + + return { nparse_rule, nparse_index, excludes }; + } + + /** + * 解析空格分割后的原生表达式中的一条记录,正确处理eq的索引,返回处理后的ret + * @param doc: cheerio.load() load后的dom对象 + * @param nparse: 解析表达式 + * @param ret: 当前返回值 + * @returns {Cheerio} + */ + parseOneRule(doc, nparse: string, ret) { + const { nparse_rule, nparse_index, excludes } = this.getParseInfo(nparse); + + if (!ret) ret = doc(nparse_rule); + else ret = ret.find(nparse_rule); + + if (this.contains(nparse, ':eq')) ret = ret.eq(nparse_index); + + if (excludes.length > 0 && ret) { + ret = ret.clone(); // 克隆一个,避免直接remove影响原始DOM + // ret = ret.toArray().map(element => doc(element)); + + for (let exclude of excludes) { + ret.find(exclude).remove(); + } + } + + return ret; + } + + /** + * 解析空格分割后的原生表达式,返回处理后的ret + * https://pyquery.readthedocs.io/en/latest/api.html + * @param html + * @param parse + * @returns {Cheerio} + */ + pdfa(html: string, parse: string): string[] { + if (!html || !parse) return []; + parse = this.parseHikerToJq(parse); + + const doc = cheerio.load(html); + if (PARSE_CACHE) { + if (this.pdfa_html !== html) { + this.pdfa_html = html; + this.pdfa_doc = doc; + } + } + + const parses = parse.split(' '); + let ret: cheerio.Cheerio | null = null; + for (const nparse of parses) { + ret = this.parseOneRule(doc, nparse, ret); + if (!ret) return []; + } + + const res: string[] = (ret?.toArray() ?? []).map((item: any) => { + const res_html = `${doc(item)}`; // outerHTML() + // const res_html = doc(item).html(); // innerHTML() + return res_html ? res_html : ''; // 空值检查,将 null 值转换为空字符串 + }); + return res; + } + + pdfl(html: string, parse: string, list_text: string, list_url: string, url_key: string): string[] { + if (!html || !parse) return []; + parse = this.parseHikerToJq(parse, false); + const new_vod_list: any = []; + + const doc = cheerio.load(html); + const parses: string[] = parse.split(' '); + let ret: cheerio.Cheerio | null = null; + for (const pars of parses) { + ret = this.parseOneRule(doc, pars, ret); + if (!ret) return []; + } + + ret!.each((_, element) => { + new_vod_list.push(`${doc(element)}`); // outerHTML() + // new_vod_list.push(doc(element).html()); // innerHTML() + }); + + return new_vod_list; + } + + /** + * 解析空格分割后的原生表达式,返回处理后的ret + * https://pyquery.readthedocs.io/en/latest/api.html + * @param html + * @param parse + * @returns {Cheerio} + */ + pdfh(html: string, parse: string, baseUrl: string = ''): string { + if (!html || !parse) return ''; + + const doc: cheerio.Root = cheerio.load(html); + if (PARSE_CACHE) { + if (this.pdfa_html !== html) { + this.pdfa_html = html; + this.pdfa_doc = doc; + } + } + + if (parse == 'body&&Text' || parse == 'Text') { + //@ts-ignore + return doc.text(); + } else if (parse == 'body&&Html' || parse == 'Html') { + return doc.html(); + } + + let option: string | undefined; + if (this.contains(parse, '&&')) { + const parts: string[] = parse.split('&&'); + option = parts[parts.length - 1]; + parse = parts.slice(0, -1).join('&&'); + } + parse = this.parseHikerToJq(parse, true); + const parses: string[] = parse.split(' '); + + let ret: string | cheerio.Cheerio | null = null; + for (const nparse of parses) { + ret = this.parseOneRule(doc, nparse, ret); + if (!ret) return ''; + } + if (option) { + switch (option) { + case 'Text': + ret = (ret as cheerio.Cheerio)?.text() || ''; + break; + case 'Html': + ret = (ret as cheerio.Cheerio)?.html() || ''; + break; + default: + // 保留原来的ret + let original_ret = (ret as cheerio.Cheerio)?.clone(); + let options = option.split('||'); + let opt_index = 0; + for (let opt of options) { + // console.log(`opt_index:${opt_index},opt:${opt}`); + opt_index += 1; + ret = original_ret?.attr(opt) || ''; + // console.log('ret:', ret); + if (this.contains(opt.toLowerCase(), 'style') && this.contains(ret, 'url(')) { + try { + ret = ret.match(/url\((.*?)\)/)![1]; + // 2023/07/28新增 style取内部链接自动去除首尾单双引号 + ret = ret.replace(/^['"]|['"]$/g, ''); + } catch { + } + } + if (ret && baseUrl) { + const needAdd = this.test(URLJOIN_ATTR, opt) && !this.test(SPECIAL_URL, ret); + if (needAdd) { + if (ret.includes('http')) { + ret = ret.slice(ret.indexOf('http')); + } else { + ret = urlJoin.resolve(baseUrl, ret); + } + } + } + if (ret) { + break; + } + + } + + } + } else { + ret = `${ret}`; + } + + return ret; + } + + pd(html: string, parse: string, baseUrl: string = ''): string { + if (!baseUrl) baseUrl = this.MY_URL; + return this.pdfh(html, parse, baseUrl); + } + + pq(html: string) { + return cheerio.load(html); + } + + pjfh(html: any, parse: string, addUrl = false): string { + if (!html || !parse) return ''; + + try { + html = typeof html === 'string' ? JSON.parse(html) : html; + } catch { + console.log('字符串转json失败'); + return ''; + } + + if (!parse.startsWith('$.')) { + parse = '$.' + parse; + } + + let ret = ''; + const paths = parse.split('||'); + for (const path of paths) { + const queryResult = jsonpath.query(html, path); + if (Array.isArray(queryResult)) ret = queryResult[0] ? `${queryResult[0]}` : ''; + else ret = queryResult ? `${queryResult}` : ''; + + if (addUrl && ret) { + ret = urlJoin.resolve(this.MY_URL, ret); + } + if (ret) break; + } + + return ret; + } + + pj(html: any, parse: string): string { + return this.pjfh(html, parse, true); + } + + pjfa(html: any, parse: string): any[] { + if (!html || !parse) return []; + + try { + html = typeof html === 'string' ? JSON.parse(html) : html; + } catch { + return []; + } + + if (!parse.startsWith('$.')) parse = '$.' + parse; + + const result = jsonpath.query(html, parse); + if (Array.isArray(result) && Array.isArray(result[0]) && result.length === 1) { + return result[0]; // 自动解包 + } + + return result || []; + } +} + +export default Jsoup; diff --git a/docs/ruleDesc.md b/docs/ruleDesc.md index 60bf963e..8f3a7cd8 100644 --- a/docs/ruleDesc.md +++ b/docs/ruleDesc.md @@ -1,4 +1,5 @@ ### 代码格式化压缩成一行教程 + ```text npm install uglify-js -g uglifyjs xx.js -o xx.min.js @@ -11,114 +12,118 @@ $FileDir$ ``` ### 模板规则说明 + 所有相关属性说明 + ```javascript var rule = { - 类型:'影视',//影视|听书|漫画|小说 - title:'',//规则标题,没有实际作用,但是可以作为cms类名称依据 - 编码:'',//不填就默认utf-8 - 搜索编码:'',//不填则不编码,默认都是按utf-8.可优先于全局编码属性.比如网页源码编码是gbk,这里可以指定utf-8搜索独立编码。多数情况这个属性不填或者填写gbk应对特殊的网站搜索 - host:'',//网页的域名根,包含http头如 https://www,baidu.com - hostJs:'print(HOST);let html=request(HOST,{headers:{"User-Agent":PC_UA}});let src = jsp.pdfh(html,"ul&&li&&a&&href");print(src);HOST=src.replace("/index.php","")',//网页域名根动态抓取js代码。通过HOST=赋值 - homeUrl:'/latest/',//网站的首页链接,可以是完整路径或者相对路径,用于分类获取和推荐获取 fyclass是分类标签 fypage是页数 - url:'/fyclass/fypage.html[/fyclass/]',//网站的分类页面链接 - detailUrl:'https://yanetflix.com/voddetail/fyid.html',//非必填,二级详情拼接链接,感觉没啥卵用 - searchUrl:'',//搜索链接 可以是完整路径或者相对路径,用于分类获取和推荐获取 **代表搜索词 fypage代表页数 - searchable:0,//是否启用全局搜索, - quickSearch:0,//是否启用快速搜索, - filterable:0,//是否启用筛选, - filter:{},// 筛选条件字典 + 类型: '影视',//影视|听书|漫画|小说 + title: '',//规则标题,没有实际作用,但是可以作为cms类名称依据 + 编码: '',//不填就默认utf-8 + 搜索编码: '',//不填则不编码,默认都是按utf-8.可优先于全局编码属性.比如网页源码编码是gbk,这里可以指定utf-8搜索独立编码。多数情况这个属性不填或者填写gbk应对特殊的网站搜索 + host: '',//网页的域名根,包含http头如 https://www,baidu.com + hostJs: 'print(HOST);let html=request(HOST,{headers:{"User-Agent":PC_UA}});let src = jsp.pdfh(html,"ul&&li&&a&&href");print(src);HOST=src.replace("/index.php","")',//网页域名根动态抓取js代码。通过HOST=赋值 + homeUrl: '/latest/',//网站的首页链接,可以是完整路径或者相对路径,用于分类获取和推荐获取 fyclass是分类标签 fypage是页数 + url: '/fyclass/fypage.html[/fyclass/]',//网站的分类页面链接 + detailUrl: 'https://yanetflix.com/voddetail/fyid.html',//非必填,二级详情拼接链接,感觉没啥卵用 + searchUrl: '',//搜索链接 可以是完整路径或者相对路径,用于分类获取和推荐获取 **代表搜索词 fypage代表页数 + searchable: 0,//是否启用全局搜索, + quickSearch: 0,//是否启用快速搜索, + filterable: 0,//是否启用筛选, + filter: {},// 筛选条件字典 // 默认筛选条件字典(不同分类可以指定同样筛选参数的不同默认值) - filter_def:{ - douyu:{ - area:'一起看', - other:'..' + filter_def: { + douyu: { + area: '一起看', + other: '..' }, - huya:{ - area:'影音馆', - other:'..' + huya: { + area: '影音馆', + other: '..' } - }, + }, // 筛选网站传参,会自动传到分类链接下(本示例中的url参数)-url里参数为fyfilter,可参考蓝莓影视.js - filter_url:'style={{fl.style}}&zone={{fl.zone}}&year={{fl.year}}&fee={{fl.fee}}&order={{fl.order}}', + filter_url: 'style={{fl.style}}&zone={{fl.zone}}&year={{fl.year}}&fee={{fl.fee}}&order={{fl.order}}', // 注意,由于猫有配置缓存,搜索配置没法热加载,修改了js不需要重启服务器 // 但是需要tv_box进设置里换源使配置重新装载 - headers:{//网站的请求头,完整支持所有的,常带ua和cookies - 'User-Agent':'MOBILE_UA', + headers: {//网站的请求头,完整支持所有的,常带ua和cookies + 'User-Agent': 'MOBILE_UA', "Cookie": "searchneed=ok" }, // 海阔一级列表样式 - hikerListCol:"avatar", + hikerListCol: "avatar", // 海阔推荐列表样式 - hikerClassListCol:"avatar", - timeout:5000,//网站的全局请求超时,默认是3000毫秒 - class_name:'电影&电视剧&动漫&综艺',//静态分类名称拼接 - class_url:'1&2&3&4',//静态分类标识拼接 + hikerClassListCol: "avatar", + timeout: 5000,//网站的全局请求超时,默认是3000毫秒 + class_name: '电影&电视剧&动漫&综艺',//静态分类名称拼接 + class_url: '1&2&3&4',//静态分类标识拼接 //动态分类获取 列表;标题;链接;正则提取 不需要正则的时候后面别加分号 - class_parse:'#side-menu:lt(1) li;a&&Text;a&&href;com/(.*?)/', + class_parse: '#side-menu:lt(1) li;a&&Text;a&&href;com/(.*?)/', // 除开全局过滤之外还需要过滤哪些标题不视为分类 - cate_exclude:'', + cate_exclude: '', // 除开全局动态线路名过滤之外还需要过滤哪些线路名标题不视为线路 - tab_exclude:'', + tab_exclude: '', //移除某个线路及相关的选集|js1 - tab_remove:['tkm3u8'], + tab_remove: ['tkm3u8'], //线路顺序,按里面的顺序优先,没写的依次排后面|js1 - tab_order:['lzm3u8','wjm3u8','1080zyk','zuidam3u8','snm3u8'], + tab_order: ['lzm3u8', 'wjm3u8', '1080zyk', 'zuidam3u8', 'snm3u8'], //线路名替换如:lzm3u8替换为量子资源|js1 - tab_rename:{'lzm3u8':'量子','1080zyk':'1080看','zuidam3u8':'最大资源','kuaikan':'快看', - 'bfzym3u8':'暴风','ffm3u8':'非凡','snm3u8':'索尼','tpm3u8':'淘片','tkm3u8':'天空',}, + tab_rename: { + 'lzm3u8': '量子', '1080zyk': '1080看', 'zuidam3u8': '最大资源', 'kuaikan': '快看', + 'bfzym3u8': '暴风', 'ffm3u8': '非凡', 'snm3u8': '索尼', 'tpm3u8': '淘片', 'tkm3u8': '天空', + }, // 服务器解析播放 - play_parse:true, + play_parse: true, // play_json 传数组或者 类 true/false 比如 0,1 如果不传会内部默认处理 不传和传0可能效果不同 // 效果等同说明: play_json:[{re:'*', json:{jx:0, parse:1}}], 等同于 play_json:0, - play_json:[{ - re:'*', - json:{ - jx:1, - parse:1, + play_json: [{ + re: '*', + json: { + jx: 1, + parse: 1, }, }], //控制不同分类栏目下的总页面,不填就是默认999.哔哩影视大部分分类无法翻页,都需要指定页数为 1 - pagecount:{"1":1,"2":1,"3":1,"4":1,"5":1,"7":1,"时间表":1}, + pagecount: {"1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "7": 1, "时间表": 1}, // 自定义免嗅 - lazy:'', + lazy: '', // 首页推荐显示数量 - limit:6, - double:true,//是否双层列表定位,默认false + limit: 6, + double: true,//是否双层列表定位,默认false // 对图片加了referer验证的有效,海阔专用,普通规则请勿填写此键值 - 图片来源:'@Referer=http://www.jianpianapp.com@User-Agent=jianpian-version350', + 图片来源: '@Referer=http://www.jianpianapp.com@User-Agent=jianpian-version350', // 替换所有图片链接 欲替换文本=>替换为文本 - 图片替换:'https://www.keke6.app/=>https://vres.a357899.cn/', - + 图片替换: 'https://www.keke6.app/=>https://vres.a357899.cn/', + // js写法,仅js模式1有效.可以用于代码动态获取全局cookie之类的 // 可操作变量有 rule_fetch_params,rule,以及基础的网页访问request,post等操作 - 预处理:'rule_fetch_params.headers.Cookie = "xxxx";', + 预处理: 'rule_fetch_params.headers.Cookie = "xxxx";', // 类似海阔一级 列表;标题;图片;描述;链接;详情 其中最后一个参数选填 // 如果是双层定位的话,推荐的第2段分号代码也是第2层定位列表代码 - 推荐:'.col-sm-6;h3&&Text;img&&data-src;.date&&Text;a&&href', + 推荐: '.col-sm-6;h3&&Text;img&&data-src;.date&&Text;a&&href', // 类似海阔一级 列表;标题;图片;描述;链接;详情 其中最后一个参数选填 - 一级:'.col-sm-6;h3&&Text;img&&data-src;.date&&Text;a&&href', + 一级: '.col-sm-6;h3&&Text;img&&data-src;.date&&Text;a&&href', //二级发起访问前进行js处理。解决特殊情况一级给出的链接非二级真实源码而是前端重定向链接的源码 - 二级访问前:'log(MY_URL);let jump=request(MY_URL).match(/href="(.*?)"/)[1];log(jump);MY_URL=urljoin2(MY_URL,jump)', + 二级访问前: 'log(MY_URL);let jump=request(MY_URL).match(/href="(.*?)"/)[1];log(jump);MY_URL=urljoin2(MY_URL,jump)', // 二级可以是*,表示规则无二级,直接拿一级的链接进行嗅探 // 二级 title: 片名;类型 // 二级 desc: 主要信息;年代;地区;演员;导演 // 或者 {title:'',img:'',desc:'',content:'',tabs:'',lists:'',tab_text:'body&&Text',list_text:'body&&Text',list_url:'a&&href'} 同海阔dr二级 - 二级:'*', + 二级: '*', // 搜索可以是*,集成一级,或者跟一级一样的写法 列表;标题;图片;描述;链接;详情 - 搜索:'*', + 搜索: '*', // 本地代理规则,可用于修改m3u8文件文本去广告后返回代理文件地址,也可以代理加密图片 - proxy_rule:`js: + proxy_rule: `js: log(input); input = [200,'text;plain','hello drpy'] `, //是否启用辅助嗅探: 1,0 - sniffer:1, + sniffer: 1, // 辅助嗅探规则 - isVideo:"http((?!http).){26,}\\.(m3u8|mp4|flv|avi|mkv|wmv|mpg|mpeg|mov|ts|3gp|rm|rmvb|asf|m4a|mp3|wma)", + isVideo: "http((?!http).){26,}\\.(m3u8|mp4|flv|avi|mkv|wmv|mpg|mpeg|mov|ts|3gp|rm|rmvb|asf|m4a|mp3|wma)", // 辅助嗅探规则js写法 - isVideo:`js: + isVideo: `js: log(input); if(/m3u8/.test(input)){ input = true @@ -128,28 +133,35 @@ var rule = { `, } ``` + 模板继承写法 + ```javascript -var rule = Object.assign(muban.mxpro,{ -title:'鸭奈飞', -host:'https://yanetflix.com', -url:'/index.php/vod/show/id/fyclass/page/fypage.html', -class_parse:`.navbar-items li:gt(1):lt(6);a&&Text;a&&href;.*/(.*?).html`, +var rule = Object.assign(muban.mxpro, { + title: '鸭奈飞', + host: 'https://yanetflix.com', + url: '/index.php/vod/show/id/fyclass/page/fypage.html', + class_parse: `.navbar-items li:gt(1):lt(6);a&&Text;a&&href;.*/(.*?).html`, }); ``` + 模板继承写法(新) + ```javascript var rule = { -title:'cokemv', -模板:'mxpro', -host:'https://cokemv.me', -class_parse:`.navbar-items li:gt(1):lt(7);a&&Text;a&&href;/(\\d+).html`, + title: 'cokemv', + 模板: 'mxpro', + host: 'https://cokemv.me', + class_parse: `.navbar-items li:gt(1):lt(7);a&&Text;a&&href;/(\\d+).html`, } ``` + 模板继承写法(自动匹配) + ```text 注意事项:自动匹配只支持能从HOST获取分类的cms模板站,采集1,短视2等api的模板无法匹配 ``` + ```javascript var rule = { 模板: '自动', @@ -167,7 +179,8 @@ var rule = { } ``` -源正则写法说明 +源正则写法说明 + ```text 属性class_parse按;分隔后取[3]为分类的正则字符串。 这里的正则跟js的/.*/这种写法相比,由于是字符串,需要实现字符串标准。 @@ -188,12 +201,13 @@ proxy_rule参数input赋值格式为三元素列表[status,content-type,data] 如: [200,'text/plain','hello drpy'] input = [200,'application/vnd.apple.mpegurl',m3u8] rsa加解密说明: + ```js RSA.encode(data, key, option); RSA.decode(data, key, option); ``` -### 其它类型源说明 +### 其它类型源说明 默认drpy源都是为早期的tvbox而生的,因此只支持影视类型的源(听书也当影视用)。 现在已三端支持,拥抱海阔视界和zyplayer生态。 @@ -201,4 +215,11 @@ RSA.decode(data, key, option); 实验特性:支持 类型:'影视',//影视|听书|漫画|小说 影视和听书用法一致不需要调整。 漫画需要在选集播放lazy处理后的url里返回 pics:// 协议,用法同海阔。参考源【第一韩漫】 -小说需要在选集播放lazy处理后的url里返回 novel:// 协议,内容为json文本。如 novel://{"title":"章节名称","content":"章节内容"} +小说需要在选集播放lazy处理后的url里返回 novel:// 协议,内容为json文本。如 novel://{"title":"章节名称","content":" +章节内容"} + +## pd系列网页定位写法参考 + +1. [C#版本代码](./other/htmlParser.cs) +2. [JAVA版本代码](./other/htmlParser.java) +3. [TS版本代码](./other/htmlParser.ts) diff --git a/docs/updateRecord.md b/docs/updateRecord.md index cfc7b43a..6959904f 100644 --- a/docs/updateRecord.md +++ b/docs/updateRecord.md @@ -1,5 +1,13 @@ # drpyS更新记录 +### 20260113 + +更新至V1.3.16 + +1. 新增全局 `executeParse` 函数,ds/cat源可实现获取本地自建解析链接 +2. 写源说明文档里增加了其它几种语言的 htmlParser实现,可供参考 +3. 更新了部分源 + ### 20260112 更新至V1.3.15 diff --git a/jx/_30wmv.js b/jx/_30wmv.js new file mode 100644 index 00000000..1df6a6a3 --- /dev/null +++ b/jx/_30wmv.js @@ -0,0 +1 @@ +H4sIAAAAAAAAA81X61MTVxT/nr/immHcRMNuEqBgGKYDkWoRjMNjWqd2YNncJAub3XUfwYiZQVuZtghDW6yvitJKdUYN2tYHiPDHNLuBT/4LPXcfeWxiq/VL98Nm995zfuf1uydnGQaV722Vdhb2nnxVXnkwNjz4Zvumj2FQRtPkGMMIEscKGUnVYh2dHZ2MzCoqZsbbwjPZ3Me6IvQ4YjhLRyNJLUdzUpZRJTGtMpFwOHykrT0SprPTOR+BNDa2jcvrx0eHBvc2XphPLxkv1o3LL3ycJKoamk1j7biWFQqoB7XQCj6r8woOUDQzLvCT1jtWNXpKpYKOQpLV2BM4D+LUiejZtmk9PtA/gM9FhnPTSvbY2OftI+LoZyfxoKzIVLePOXTIhw6hvfu/mqvLxo0H+5cXy6+Lxsbm3tM1smEUb5Y2vy1tzTuu3fuztLtmXtyAPcYxOHUObM36EFwZzCaxEnPeyEWNqVhp7U1jUaNi6FR8fKw3hJpckIbS613I9Kl4+eFGVakKNIxTWMEKoFBOckk+6WxelTSJ5jiqArRX3IEYzNvr5tby/tqz/du/vNm+Yj5YMxfulF4tGcXr5k+b5Yc3ypc294q7+9eKlo1CyFfo9vl8rJoXOZTSRU7jJREJ7Pl8gBdlXQshKDKbVYNOdGCIxC8JmBakdICyhGJUCFkPwW5LyHqG9Fi/dJbVuEzA5sEZJnAmeTjIBL+IfNn97oACtisMmAMjiZO0qim8mOZT+QA7w/IawiKn5GUtMDHrF/XsJFb8sZZZC6BQmAg6IJqSrykRgZRkEq1aKaR72QVVY57lxspS0jSpCtNGd9FhKtQoHZdEEVs5JdInMJZbewU+h5vJ9nIclrXWfpGTkhAdUUif5+VmojlW4CEfEuGFnYHKSiDY3A0NPG4dzcuY4LKyLPAcS/xipqAw3YjLkLOs9ehaqrWLqkMo1ANmsZaRkgAiQx/wOEdqFLPu9etElNiOIV1M4hQv4mS9gMZnsQR1Rx3QJyo7he66cimYlMqOF1pAoPmJYIQ8J0lkjeEEHqJmch2WCANNQ8kz0KeAXU7pgw0Woi7HrObm8CuJbX7BPvQ0K5fQhGSB5aAp+QGOooLBGiwgtYI1XRG9dJ21UGMoHELgR8wySFv5qnaRf6JYoVBjxTEx+x+R7AaAOHI8UQAHa9iuZRRpBol4BvUrCuGUbbTgKzS0Cvfo2aancR5Obs7FajxyIG636TjRkgZGaFihx7RUl5NwQEAXLrj93FMfkE3IWuOBldkkOTKxKiqs0KemObXTQ14piWukyCvdH+9rxjg+hQJ8Dh08CPHQUMBsIIgO9PSQUnusO17RIP32uCAp3U21iA+1epZP8b54VbrgzcEwVnVBq1Xq7bcM1lTCTnTINdNImwoOrUkjFkErZW7KCUdN1AXh7WxwD4rjC04e/XdakEQfqFPwJrjBdGNWwPAH8Aq0/4e8crx6T165Wu/LK9Brzqu31NTOeMi110iwCmCVYA1BfDjjYFAc4dMiC6L4E15khYAqhlCW5ULWn4qqsVm5ZniJwEBrLmybS+vG0h3j/oJ59Ym5WPxr7uL+4xXzj6vwajy+Zvxwxbi1BUNg+dayMbft6u7Pvdrb+R4Aho52gBV0mJiBe8UOPPtbI+0fHenobG+PdPjJ+9DpkcRoYrwvkRj69OQxf9ACs0dI0FLZNI5AwidaZlWx0DILgHCvABZq0OqBJrprgDKsmonUlo046KIH6863G0sUwjCezJcfPSq9nNu//twsPiu/+tFc/bn0csnOHgRozC+aj9acdH1319iYb5oK27ybDVVsEmPUjtGSrIQJETthOJVu5n+03v9GAtRMPk3bi+1HtUY9CPiLaVGaCQQbWl9VAcKHMyl2hgeHpk53puJsV6Ivnug6TXkFSdQgGe4N9x7tix7pikfbKSfPLudoVF65Y36zXH68Yywveg0BeytjzTuxuR49SiNz9ev9ubvWrIGAvuVHv5Ve/u4xQxpfYnKqocX5Adwfs0zUrxO/YIP8eHesde9qxT/YrDx7NTWITAUBv6rDtKuq/mYdsuowFKdx5Hci8aShjUbQrJBNU2Pz+d7uinFr1dtL6j8XHBMwvs1IU7w+qadZSdVFcF5MC0ArFeaoPKtLmCcjXu2aKMCa60Hz7uV+1WBrgvL32zYJY1MsL+BkzA9/zjW0885c/kHyse3Sm+jBK6cLbA2GvzqY/Q2jRI9Yuw8AAA== \ No newline at end of file diff --git a/libs/drpyS.js b/libs/drpyS.js index e0827c86..6d57ba76 100644 --- a/libs/drpyS.js +++ b/libs/drpyS.js @@ -16,7 +16,7 @@ import {createWebDAVClient} from '../utils/webdav.js'; import {createFTPClient} from '../utils/ftp.js'; import {ENV} from '../utils/env.js'; import {getContentType, getMimeType} from "../utils/mime-type.js"; -import {getParsesDict, getSitesMap, pathLib, es6_extend_code, req_extend_code} from "../utils/file.js"; +import {getParsesDict, getSitesMap, pathLib, executeParse, es6_extend_code, req_extend_code} from "../utils/file.js"; import {getFirstLetter} from "../utils/pinyin-tool.js"; import {reqs} from "../utils/req.js"; import {toBeijingTime} from "../utils/datetime-format.js" @@ -285,6 +285,7 @@ export async function getSandbox(env = {}) { axiosX, URL, pathLib, + executeParse, qs, Buffer, URLSearchParams, diff --git a/public/index.html b/public/index.html index ec8fb831..7d7fa973 100644 --- a/public/index.html +++ b/public/index.html @@ -14,7 +14,8 @@

drpyS(drpy-node)

常用超链接

  • 本项目主页-免翻
  • -
  • 接口文档 | 接口列表如定时任务 | 小猫影视-待对接T4
  • +
  • 接口文档 | 接口列表如定时任务 | +小猫影视-待对接T4
  • 代码质量评估工具说明 | DS项目代码评估报告
  • 本地配置接口-动态本地
  • 本地配置接口-动态外网/局域网
  • @@ -62,20 +63,13 @@

    免费壳子推荐

    更新记录

    +

    20260113

    +

    更新至V1.3.16

    20260112

    更新至V1.3.15

    -

    20251017

    -

    更新至V1.3.14

    -

    20251015

    -

    更新至V1.3.13

    -

    20251014

    -

    更新至V1.3.12

    -

    20251013

    -

    更新至V1.3.11

    -

    20251012

    -

    更新至V1.3.10

    点此查看完整更新记录

    注意事项

    总是有人遇到各种奇葩问题,像什么没弹幕,访问/config/1服务马上崩溃等等,能自行解决最好,解决不了我建议你使用下方安装教程 diff --git a/spider/catvod/TuneHub[B].js b/spider/catvod/TuneHub[B].js index 743cacc7..b591eb88 100644 --- a/spider/catvod/TuneHub[B].js +++ b/spider/catvod/TuneHub[B].js @@ -1,9 +1,9 @@ /** - title: "TuneHub", - more: { - sourceTag: "音乐", - errorPlayNext: true - } + title: "TuneHub", + more: { + sourceTag: "音乐", + errorPlayNext: true + } @header({ searchable: 1, filterable: 1, @@ -13,4 +13,4 @@ }) */ -49C57C16005D76F2E1EAE4A87E44399FD8FA9EB639A8DB67273AAE010E4A267D74CBCCE33F3FD3E55732E58E8E4F75F5D5FE3E1E9A49C6F1DAC30B212673A40F68344F727EC7AA38F51D2F038EE87D9CB7EA39DDDACF0B1B321F37AD955B9BEE3C414AD8C39BB1809D16BA2890C82375D9B6581AC8150290986CDDA413FBE5134C029A46C70DC7B9022818D3EEBD37587914D13143162B5644F387B783B7F0CE2A574258097A4A43575D031EAD5CA64EA935BBAA7FF5F16D996DAE87AFE5F16260247A4F9A7F4DC6023DF3A3C51B8DE81823B0760A93960FB89B758DD661BA936C2C202629EFDFE47AAD723128868B3492C12666440DF75DF487D870AEF263FAEA5EC956C82987F0AA8CB2F9B9841DA480F318EC4CACC79259521381F9E405EF8E78C6CD2FA5BBBD216541A5F6FDEB8ECDFDE8D28FFA7AA4032D42DD5E2D1D8C8D91D3A8A44F9BC1D52A853C3AB61AB8C4C17B3F6D341A8974E43EE26C75EB5D43E03A35B30FCCD3746DF7BA68336FA799674CBE5B28D98814D03A5452444EF27FE2DB4919550FCCAB1AF2BE6458A82D76A3F61D6D0E40651F562EBAB2FFEE8FD3C3EB8CCD277B3B91AC8F3AF9073480F1A818F7C29CA39D70D593E863BE4E8A1FAC9EC181656AFDE79F4F893F71F01B0001ECC092C557B589D4583EA7113981ADB82A99CB86F46711A5643535501166A765D5B9C5C36207249BB1546088A9D60BE5CF1E9D10BB39B52449CC3A3227E67A80BFF960E08F02157255D1C257F6AB6EFE76CD7FC6CFC06EB80BB01EA5EDCFF70CD37728555D6372A26C8E4DE1E677FC71C57D39AB7B32CFF1497DA645AE38CB2277895B6CFC0799A15CE98AAF389D9472413AD97024C3E0FB7145FF57CA3747FE8B8086F864FDA33CDE307484775BC68681A5D24009478FB62C9FF18AAEB13E2647485F9BE7D2EBD4049B683A69E13A87AB96A9E7C8BB913F3D581270503A76258D6429B04D6FBD4CE3D36289CA9DDAC9D913C3B69E770D8ADDBFE8430CEA197B18C4A670DB864C801E96AC6D5D3EE4CB0011E4C0867855C187F108C69E9A618976198B9B038E6A5E768E41BDC6666C0DC47AF520A49559F85290CCA5CD367B18A58EA94089C8E4A4F99FD4FB43C8F9BCEBE40895150BC3A68A1936153529F80FAEA92E524ADB5ADED9EFDF7B80B4F475629E975218C71145CFCCF8320A68C3CD28E9CBC9308947F99C4F1707AF3961E564DD706B8BB57336C8A4B565F20AE677D3A389F3B8BDB567196C08BEBEB745D28A0067138EE1D06F855EBAC29651E9A85310371309FD00E70F50DD2E9492CE5CCB0686D830CB38591388C708EAEC826A9DF82D2DD36FEAA0AEE97F5B0FC580D1357A59C4A0448BD6AE22987529748710D30AFB68EE801588C96F3B9FE27E3757AF53A2FC545BF8DA08D9C7E21CA0B1FD2B46DE51A420EBBC94E8B41B35D3BF6873173DB295CB8E55631CBC19467CA95FBDB7D2D3DE8E8123BE4291C0F575A0E06D3D3AFD2D03E25A5C24E3D3B34D5E91CD61F2775875143E30FA87BE75C04E681E6A3B84963A1FB3D5AE485A4935300621DB8D61723C6B1A80608E86F16C116F4FF35BE86415F33BB7BC8E1324EC1E59F4CAE2928ADDE1854BA70EE2A4984936A6995001E84D1D920384971D07530F01FBF2A4D26380EB253FC6F7A992BD3D48403B6953EA415A49F93FB010F13D4B47802EEDB671849762199A5D994B07F53F71C17E9C31A42E7F301C361F341DAA15ACEAEB4497ED00D6A2BD4F92C79C210665AD075847D4C75F83AE4948635EC4C610E130C783F694D881B3B3B272897EFB077AA57F7C5C002EA8BDE6F283C366234114A10663AB292E8D63096C1A71D0C434AFBA029B3E8A61A7DCAF489A64A028A67F118B09A17C949ADB008E0F9613E5FD608120C0772372BA291642A9572F4FBDCDB61FFBC9ACABC72CF59B9EC963ED270BF971FCB4DCF6220C8DE7CBD8C23D9EFF7372CCCDB4B2FDA1E3FE6BD3D2107B2918D22EDA43C758DC642C7965D25A7994EEE159F7B4200759F7B19DD7B35062D9D0FD0F73DFE53778B6108367152C4F3EA86849584E998159761A28DC3E66AC8280E188A0E85E19BFDB607368D60829AFB6E0781A825A22E0F207EEF4D2DECB8BE17016E2558C121BA6490FC683236004373EF6FD292F9CF15CFADBE447560A6CEBBADD4EC55763EC33CA81B30F4D73AC75D4F4EB07DB0841AB45822781558366755C68A2FCB09415BC7A413881F5086628EC1982C0BEA1E5391F9E6090B345F5AF07339F1A292D21FB8E69DB0AFA8ADFDC38FD15B7EDD7CA1F515308E2E675246A567C651A659C86E30BFE86CEB3A24C92DDD7D5F3979318DE93C8E44293D23A8EC05F6D60CD9D975C06256A835208F24F4C375DA2ED5AD081E9A07AD4321E84AF45EF35F36673CB0028FD6133E4AEF95CB87CCCCB4C5F3EE04572B661E3C0018061001B7FBC247D17BCAD70DF4EF35C6E4B394AF95CB39D66051661422614D7A99141B3740FFFEA8730C56C7F108CD3B878EB0FF1F55F56D73F11A63B6CE749FF06C7034F549B84732B8B3134EA475A41F5A7754B346870AEF263FAEA5EC956C82987F0AA8CB43579764937CAE17DCE483DA217E771D719855AA51C29AE5A175E5351AF41252CF56C6926C382D9B49A1894B2533B80D274B8A20D46310EA441D91533196B69991233E4A34E1DBF4020037E8B02D753FA5EE1FBAC2A654815A9A1FAD37AA5CA1F30E367F33D164D0E242317673D7EE1DDFA555E09D754BDE842F6DB40489D56AAEC6D21915A4CE8100AF34573622FC7FB249737B79B9AF95F8F7658ECC9557D2EE26C75EB5D43E03A35B30FCCD3746DF7BA68336FA799674CBE5B28D98814D03199575D9C26FCB81FB4ACF769CFCCAF2C04D827BB19526148E8104D1EFB0AD8C54C8442A9A662CF7F8D18865FAD41D45CDCA40C1C374BEDC05620CB49BAA2D42CF16F6D1B74D958410A5F7F8AEE94B83F80D3430FEA113409750F51069E8D44551EBF01B1D82EBB4A4317F8C91A3E3B5E1E47234CD0347715E59B0A72C448AF4E1998110B4F9EA8A8C04034615F7130FAB7E142587D9311D38901B027C4C377468735EBF1F7DB23E863731D5762B07FD6A82C5284D560840668C9C7AD2AF7BE418C54EBDE0EEBEAD6C535387DE337587DD51D88AD1A5E55CD1EE982BB2BF32F4F99E66EFB9BB03C20525F02A80B6E53DB0C9C7805D5CBA9C0938BFADBCE33ED1C883A5CDEE61AB126785C0E66F86D729E52F757226B556C1BCDF5D8C58533298F99E66EFB9BB03C20525F02A80B6E53D7D329F9FFEAF8C7455FF740B0489EEE29ACA6FE48942A0F154191389E89C3007322CEB0F9373DC5BD557761D514DF02E02785758DCFDEDCF76FA89C8EF99CBB6F9BE0DAC3324FD9BF9DB237F10A262F8D4A4F0F5D7897132DB49ACF8C8F0EDDDB70BD592C49109C2EF67F58F3CEA90B15F0BD1854A3E2C7C3E49B87BED667858895D25474D432C71F43ABDA35D49BBA1C4C8AA25C64986F24E1F4F115AE0798405D97B8CBE8601F7E807F397873AE298B0DB9FFFFFA964D1A2B08876D8675BBFA4AED02703CE4DB76B6ED1D1C4698421EC740A91C9F8B233161A844B7BB124FAEB73FE92507AA634CF849B6B901DD80357DBA01D7DAB4FD672E9C65A0A0CC20E04D9E5E155CA122E5EE1A7122716A60073DF85BE18B2AF8DCC4EBFFE54C994B81B57ADD276E3CFBCA7D7D475DD7F945B7668949D94E20A43D6765AB9F27E54BEAC60A2737A05B0B6EE142560A658499833F06ABB1F01952DF6EC4F84991610C97C8E7B5CA94BC7984516929B83BDFA2F7AE9F02766268FF65DEF711B4046EDCEBD85F3D8925D65F41C7AF698045DE0238F758C1D4782E4B3DFF5AAD9E8324B1EBD85F3D8925D65F41C7AF698045DE023FEF9996E1E374075521867B07DB4022E4683922888F1DC7FA4DB62FA818D68399A518D7123E213C146D6F04622293C2514D3F20E65E5F3E6531DB37FB34A3E87BBB3D2EAC134D41AE28D13BBCABA6BEC89D97DB7F2FFF9576B8E33E6139362BC7F161CCBC3C95A9588D897601F8CFA27D009312225A18B1367B9FA1809424339A0E1A5EBDA119000532C88FFC76E732984F6172EFEA0C23CD55BAD77E95F390A782447CC26A17C85F03BE6F422D83993E7BE02FAB2E777F41363A1E9865632D81335D51F95C9C468D7C97A97F09F6D3A48A373392A7ADB704286C05BEA36E05AFB4FDA2584952E42366DDA60406B2188920838652F856098D16305706AFDF92A5EAAAB3E0DB0006054F0257C266B4EB1EDDA0BEB1F166115A892B1DAA17994CD67C44EF28B5314742AA388809C7A8DE858EAD2849C7F798547AD7764492D79D9C995806F34319ED84EF8141D17FA2CBC368B4E396E562BC15182A8E78F98F07AD6620B0F073005FEE992FBAA0067C455D233EB1981F6E0E52F95408A5A4D2ED4CB389996C1D2DD305817DFB84F11E0C768C95857428D5B1B1826B66092E7DB2F2E815CEB57006FBEBF3E30C622D5F1BE97BF3A8FF4B6DDFC04F44E3F130433B46A18A4265396A0D420417410C43D2AE1ACD6689F3851EFFAD5BE131D2CE6903A361C47AC69B40CABE96F85689B9409D6DEBBE7F694DA1EB70248F358AC450CE245864718700BA0E27AF2BA58CE9E282F5A5CF165F7096E8F8A1D98105839F62F38B3E969CF3056F585D4263A6193BFC230E18E940C8D7A00EDAC3B979F103385AD540C0C8CB909640C5AA050F368F74782ACC117F067E07BCB552465AC803AC2D0CE07E3597E2D9FDD49B4EF56DF1E3257F1D626E38B28D3D7F0F177FC7EBD9E582F813E21A94C4F464FA8647121838ACBEDC3E995CE97991DBC795B08A9D1C1F2F27416C06CDA975EDC546662C84C4EBD85F3D8925D65F41C7AF698045DE023E1531A0664F4C3C50A3208F3B4C8DF66C7724F96FE405DD5FF307F7F4C6FEDC8E8A31D5115510860B2697BA28F7044D241D3488128DD38CD5EEB5D0F975754BE369B0DF709CB84595B49BB2C64A23C9625F2231FD201B600F1DF1869E324DEC644C13BED311020D41230320C4A1107563766DBACA37669C9DDB211773C796138493D57010018948AAFD6C7210DBFE2AE26F64D64ADE840600D4901ED33AC4274767ACFB56CD4E7961A9B794DE8D9A003D01C73BC9959B38D842E52D59AC4C9D2CEC5539F6597DD4E522023235E29C43DADA96868AECD13A0191AB14A764ABF04491CCB54647ACE030655A24142C7F513085BECD5CA7E6E0C7D2CB7A862FDEF4E17AA1222674E203A979B9A6AEBA57DB37BFF688F8F7C00E8C2B70A7F19C0C034F3EE04572B661E3C0018061001B7FBC286DD1E2473104AA1F7265E8C1BEDF987F4A6CDE98BE4D895512D8D9243684437FE2F78484B789497BC33E3573544674730A36CEB1788695FB03DA5AA6A927B46AE521C3DA316E8F9561EF788F9368022C57BC830678E2A46A5BBC704E0A26995611F022348B5E4A73937FB7539F3E423C715E5F3928BD6B16B964F1E5C6CB928069F6E3F2F2BCEDD1BDE2E8CA6FDB9F16614AB7EABCC8EE9A6B23B67CDCAD6170EDF34E2BE785B14D8D5F548C00CAC0EA7BDB0518ABBFD3962DD4D6D7F41363F7D4379E61AD5F564ED126F9C9A5A56FB52A140CEBBD57D33C5A7CF27CFD7C9788A0464F01132C443F9A0E8FE0026D69875640616D909285F08A8B73EF6D3E9EAB546094F8DE14CD216A1F140EA8EFC5C2749B35D4E1576416D3B2FEA03B91A96193868837C950A97CAAB318998E38B894340B0BC4DF6C6F2CE95B6A41DD1B3377D95C1B31E6F4F2172F98307065127D91CB74738844DF6BB483699F2C3039CAAC44C344217F02E6EB880F0E53510CA3A5D02E97CC13A6F1E28F012995EF4EFC375BD1026F72503D1CD12FC4B96199E641C55B18C1E2FDD95FFB51ED7C48513E7BD85F3D8925D65F41C7AF698045DE023E1531A0664F4C3C50A3208F3B4C8DF66C7724F96FE405DD5FF307F7F4C6FEDC8BD85F3D8925D65F41C7AF698045DE023033EF147E8CC4ECF5175E02999C57F126CDE4EFF7DD5CEBAC895CF0DFAA11D2BBD85F3D8925D65F41C7AF698045DE023BB44251B0C00A9A22B0E8E0E277F5C15C5C419FC58FC3D1BC71562A0C99F23CC885151B1E57A72EE78FA0D4AA997D1B4A4112EB0951790B21F54B674BE8DC80EF43A55DF44E39A6C0090B31D37860D370BD3399CBB4A41210FB4C866D4AFA6422A354721FD9159245C0B46817BF14D6ADFD3880F2C6A8A3E63F5727FD47458C8A5605999E929D2DF7C88976CECBAA1CCC83522F2EB50019B05A50C143535CD7863C193884E9EE283AFCF32FC5083FC36A07AC03A968F1961A96B208131C4EA356882AD8B25CFAC8B56559F23FF374E0A31935E9B78B5F9BC7F31DE2827D85CB6C136259ECF5AFD7C75D0CDB36047850914B8921BB3279574048BF18A0C304562500C0A475C7225718DD6BBC502340C0F269C46F43A9015448B40A0ACEF01A0CDEF6DB5AA3EFCADCC10C3E748FE6CB42FF5F91B43C841F8CB487882A1430FDE0DDEC533BF43E27D623E82433584561FEE98C27B2609590DDE914C292E348E73AECAF5BF3C5EBD5D2CB8E76E58DADAF609FBE4228AA5CA5A97B9B43D632AD5AD2DD48EFE744EE8E5BFCB1D3126050D6EEC6CADB048E038FFE7D86B980F8805244558502C074542EEBAEA0641F9744CE066CD32D453CF2AE4B73CE8CF582C0D3B6F29E5B1DF4C911023DB6380F82DD3AAC96C433B93D5AC0143BFE6AF86A5C5AC88DE831C958AC0938ABDFC6B71EBB1A9530E8DF72B594AF325F85367E2B4BD406D89C5FA39F18617DEC9FA3FCAD57A504D668D218E2ECB89174D3C071460DE1DF04D07FC887C0F29367A798DF4AD42D487CF356F6F39BC48309E7E1F56714AB01A3A80C37FF7091ADE278C2846C17479FFBD1ABE92DFA5ACF5FEEE6EA64AF4A530E3A50AFF852AA07E1BA58AF0B440341C41D3488128DD38CD5EEB5D0F975754BEFEF9996E1E374075521867B07DB4022E4683922888F1DC7FA4DB62FA818D68399A518D7123E213C146D6F04622293C257A8644A9594A0F9BD4CC49CE2D88C5724FECAC743A96B6BCA33973BFAAD4C51CCAAA981579429DF919F62D34C03AB8E5E010E4A267D74CBCCE33F3FD3E55732EC8B2E55151A84A2704DB1572F9CF566A283B832DB04C7AFA5CAD1A4F44669DE6819692FFC5ED90F9E8BDC9EE606662E740CE72EFE40D771AEB865FFD75B234FE235D021507D4345F69F5B21CBB6257A2FDE51DBDE75A898A4F68819272A9E19E735623245E772D2DD9D27E9D1B55D1E3E427092FB61A26F910EF99D8B603D1BA5A2EDAA44E5CE1FFE643D4B66718E89DBA5F5CE59F4EFF8DACE14E053E629F5AA22421304102D2A0EA75FA03B754A2753E1B08F2B029B4D2651A187987E07950BE6DFB40937BF2C395D9188506B5D6C247D557A9A6DF1281C69DA22E83CE5364418B5CB4F21293D9CA1113802B8BEF181BB609263D29F9EAA0236DEDAC2C5562DAEAF19CF7DD37F782373EF8CBA7D72610CA46C1C65110781F268320F3C04B669A518D7123E213C146D6F04622293C25C6735C2A1F1DBA42B20C67ADEB5A0AACE26D858680A609E7A55387A24224D3BC53323C7AD61404FE7E052ECC85027C74BA4CC745758EB4512606482D35B29F8615FF3D4E1621C5828B5576CD31E6B9F99A518D7123E213C146D6F04622293C257DD76F840D8C554D8E44D21F8107E270B5D150911A9407602CBDD7C273934AA5E0D4B13229504799E1E37C07E091CF97589BFDD8A725FC6A44910CBDC1E75ECFC08C5627EB33B0CBE720324A56018E86ED4CFD53C7BC9EC9D891C66893426E1E9D6F5C8B8B75436FCEF24FC1747EB26E0CDC4ABAF45DDD56D10484FEE3B853679A518D7123E213C146D6F04622293C251607F9E555C25D256A43085B836BD51B78C52A28DF6F8BFE04B737C16E6C16DA4D1E45B053B9EDAFE7832A1610679E17B6E051807152E42C20EB2B4ECC67D9DD5DD48058B23FE47FA06819AD6D85D76C07E2FE400AB7B48C75188D4F752E0020F69B971AED8465E7125507A93A074A47D71E5976478A9BB8D89929BC2243EBE5FF056848FB06CB86684BFAFA8FC24D04D95016BF8DCA06656750A232ABF134EC9A75A56B2C446EB576FE31A9E3F0DD68759F7B19DD7B35062D9D0FD0F73DFE530C8106D66988FD29175B3BC4A469694ECEBA25D2BC00AAF3DCC48C89B9039A9D2D60807CEE5AF946E5967AA29463F87FFBAF14CA67338761A37B2949ABFAF36CBFF3D6F75DE16766D42B4CE7E0DC283EE88758653DFDBC0B6640CD551F04A385B879CB680AEA6727E872F66DA8FF4A93A7F983C9E18C611FA16E5507D227551EED743A6FBBF28BBFCE21792F93D4B95139B738204F01E303FAE6CCCDFEA07540E2D3FE0607604EB7DE21D4A5A88E9207392CAB7D45E61B17E89AA9BD5D57B655F25B3DD95391E0C28A6D6D41264BDE4ABE4AAA7D4A2CA42B3592AE59DBBDDAE27B2061ADC85D726BF7CD1B09814B1A5DC146E7B67E3204A55A1D40AEADDFF4EDBC05125616F339AB94C8D1372D8B721CE77FD07B2E160C53ECD39D83363D1CCCF56B8A269526556814F8BF95E78F06902F5B874F5D0869BD9A7E44A7F28757828B88FEB2AA3F0015D7B131D6D43C026F36001A934D056C98474C520C53AD9D17AE583CA808D25D7310CD40B4A7E40FB7AACFFA83C0B7B228B2F0652E9C7951873F02E8EA0C6EE6E1406E237332565A82F5652FA564676FA890A1541FFE4AE533EA7A8357A625FBD5E1CE4C10C735B490A06AEA75AE0DA30A97B4AF9D08B3DD1F3C506877BC7877BCDE197486C670A2B433C1304DC36A84A30EE3FE9F638204CEBE17461E78246FA12BA9DBAB14912DAABA5F5CE59F4EFF8DACE14E053E629F5AA22421304102D2A0EA75FA03B754A275C42E38504E589559471F71487450AFEE2DD4B2CAD697D15F5E32F4A8511F4C0010B29C34B5E1976823A40BF754AEB1AF554A01083F5FB0080F6C0BAE6AA623FF4725A5053197DC200C1DE33C6EEE4F57C7D60EAFBACB7EA053F4204C7A8CEC8B3D89BE58B5BCFD901C21A135DC438F5DBD8D15B1D3A6B881523A24D4780C0F72C44C344217F02E6EB880F0E53510CA3A5D02E97CC13A6F1E28F012995EF4EFC3B2B6254FE3A4CFE08048C0974D64BC4BBD85F3D8925D65F41C7AF698045DE023D33105FAFC6BE8261F5588BB41223BF8680ADDCE5587F4E0EB8B46E8971757F97E0FBE7F14FAAB29B0E4F58E8D9B0EA7832676F9F67EDC553BE422E3F8138D01D9FA2147BFE93D7FFC63645F6007078F90ACCDD16D8BCBE9B817AE1B9483942D7655802374BCA624FC653F6EC8676E47B33829047F9990CD40D520E75D276407D2F4C738077C5B09461C44B1AF7457A4B0E558AB9BC06C4697357264DB4F602CBA048DC12078AF524440D15D8CF698C406EF1D7962E51B6194FDD606DA0183E5F1027CF587BF194CB0FECB49E633DF8C8760C892E16016A68D429E55EA84208577020362D9E67CDEDA168C07F396D32B8DED79147A96E01280ECA0B6A404539CDBB36FB4ED62ED022B7E2F4A7B5D4347C2F853A12D94E0F53076625961D9734AAD1842957C04FB648185ACF4D9628B309E1E5D18D4C30CD7BA7BCB85565322E74016C3556977DEF81D1105744037FEE77C8E7B5CA94BC7984516929B83BDFA2F7AE9F02766268FF65DEF711B4046EDCE61534E072766133D47B1F0A4A6D9A9BA64092BF37808E3449E2E97B7F4C62329B3325CC279DCBD5B8BF4BEFDAFDDEBE01BB609263D29F9EAA0236DEDAC2C5562DAEAF19CF7DD37F782373EF8CBA7D726DCEB59175C30A0A181A3B1C4EF29D1080F4FAEA12F44695D4151246AACB095CFC363BDF2AEB5939EB50063ED5573AA2F71CC7D530A61A82DD3F25CD0623F5389457EDAF473E1CCE71C61F3F67945AF6B283AC2609B7B0E0FBB343CBCCFCA28727B22B9C003B72606805EE3D3916245AAE26D858680A609E7A55387A24224D3BCF45C14DC8F69566378E8CCE2EA53971967F70DF82FB035CC3D1AFFD4DEE1C85B0168570FE09419856DDEF0C4E19CBC0E759F7B19DD7B35062D9D0FD0F73DFE53156E887E4C6464BB8BA4BDD7973507EDE5A1A7364175A73DD18C458479A783CB4E39FBD97AF03D83A136C986A51D845C518EF55E0BF7B4B135BE863E04D329646780C2ECD947EC5B17986548714E1C6EBD85F3D8925D65F41C7AF698045DE0234997842DDEE0E53DD6C45BD674C1662C1BB4F8B05D6A2B25200A708BFC4BC9ACB6E087FABF24E38C355D8EB672A9100A61B0921AF3851F75DEA886E76A0879EB2B39FA9B88A8BDE32EF32CA9B87F75D13B5BE1B9ACB9A143CAEE59AA915EBD329A518D7123E213C146D6F04622293C25289D0E81B737979D426C970DCB0C4734170841D0928C823F9968A8748A0CA2FBA58F316B60CC4894564FEA18F65C99CDAF75059998BF393FD67A6048ECA298BDD486216F0D429348B803B35B3224EEF79867468E727ED4DC4B0F11FE6DBB14147129C156947A2E998726760C00DDADF985D86ED80035EB990FEF7FCFF297917E52FCB67594B459539A5AFCF4983385418F1D08DF53DED13B5044A8C03F391916B61AA6BEB701F598C70A1838A0C1C45F910B8061AFC275F67E8B88846993D7AFAF5294B9E2A38B0F7CE70C08A7435E011F422F7179CD548A59C109FDF92E57B4151FA82F1A4AF90D72736CEE2B434908119EAC9EA1BA62C6A1952B2736645981522A8418E529A82D99EC74C3CC1861268716D175F85F295B4C5D1FF78E05C91EED2213BFA616F8686BA41C16D2E4615C92FF0D57A8D09C00DE38283DB56CA7A54305FF6351601C0F30F4D0349618729A6DD572195648282BE5E9F5D459A626CB98C38490A74BD2821C96B97EE255DBE2826DB546A2BDA73F9C0AADCEC3E00B7C42F8448845108746A9F33B55EEDD62733985E34033CDE9AB53630E914A7259A5ACCD569AB22809DFB0286C3F1D0401BBFA6834E1FA4A795A80DBF097CCFE54E29A539383BDD37D314561A169EDE5CD30C52051BE3FB4B3FB9B9E61E72E84BD6C02238F0B5E3C65B197F55C26390E268DD5CFDF59EB38663EAB94B3FFBA1C1DFBCDF4BD99F055108BD23EFEDCA93FCC6D28B2CE2B6C369AA808E85C0BD0878EE9A50C32F0E35C178388367E675F6A80A24F3DA0BA80DF935535C5F1E12B01B90B61F578FAACA2BAB8C9F3772E087648C2CCA8609062038BE2ADF104EBBFB248FDA2E9C782F030D4D4C6C4C62928A410FDFA53CAB030400CE7D3E2B89704E9B6A5BD4FD3DEBE8DBD5705267D3FA8545DE66CCCEAE9112A214C1DEC90B554CCAC785E0312A1252FB9180D9A74C5ECAF92D17ECD7E107C12E70FC080A2C5C731102FFB312C8C6BE32DBC66DF36BF38790E741E50AA9B34AE9FC54C1AEB08C85B8A04AF11D3D43EF8618AE582295FA3BD81748CD1FDECF06A4B755697349AE9390B9A29D50A0EA0B7CF4276FF728138D7DE8EE337859CFCCE31593B67048CD2382988A132A47082827EC2C400236A0566A873C65D99CB0E64DA88BDB8A9E4013BD650AD884AF953350B129A52E0B6F3001B0C8762A850C5AC89735FFA4749FF5B4EA31FE9562DB91E0AC445FCD26E32A76EB11978783635B1368F191AD1BD3CF86E2FD5B57F6EC7B19B20906A868AA12114904AF627B4C24254491EE1E995081E79E6FC6D1603187F47419CBAB88C11C55DE3B5B23B8C482F684EFBE72A4DD0E7A74BA31738E6C3FBD414C08D058E779AD07DB9F98B7BBA979909B6EE8EBA25BABDECF7A6276B998D13C61CFFE8C02D4807FF355A0422E59E4A423872A315B720579962D11C64B465275B6798E3ABD847C52A94A81F310CA3688DFC9B63C5235ED8AC143C8AE78ABB546E07D4FA40546DDB5A091D804A6B0CF9F462A20BCEABC87F63747685D9C6240B074355ACF602992B4C5F0A0ED6A5746F76326D60160983F46F0BD3399CBB4A41210FB4C866D4AFA642EF961BBC5E5671DF3E2DE80E5D12CCA6D5C810D10830B95279C2237DDE4B0EF018A4FE028C8E10B6682DA1D3962D2ED30FD08AFE8E7E53B9FD3ED852CF9118442B7CA2CED841BFFC7C380E0F793FD2504165527C89BCF6E870C7169FFE6C451B0751178874F843FBB4FC057021B4DD84E8F8DC4CFB9D44E59E996E1D213BEBD80506424759E54DD4BA6F728330D9BD37EFE18BD34A34408A4057BDF48736109A01498DBFA676613FC0BE57673876878F7D6A978705E981705C8C06D911854FA79EB2769DE38E7C9EC44999F40A2F0E499ED1253C318D61803783D9F218E2D2B0A2C19E0E8D1CA37DF5122BB611533B83249599A7D676232CFD1827052463F790439F697E14115AF8BB28ECDD3E5DEC9AB2B1C519B7B7CBDE6E71A2E97E2EA19B7BB29A27B7015CC8AFDBC5269890BD23C464C6715E330C7695231BB73286F86DFEF9996E1E374075521867B07DB4022E91FBA4916E44BDC76F57AF0DD359420317110B47E64FDAA99F48CD63122EB10412461023EA3AEA5E293C3FDAC72622F91F9F69ADBC86AF71C45014CBDE8267B7BF768CFAFAA782C801672D9BEA620CD31470AE8DE70DF0C5930A0FE69346A64F5A6704E80B58B28D270215F7D4966EDBBD85F3D8925D65F41C7AF698045DE023941F6A1A1CFF0199A7D59A2C5E10CD863BDDAB65591812566A6E59962BF444A9BD2302D583393896F6563E8EE25D3FF422F499814A59E5BF5E4E824D14FFB8E06CAEAB99C61FD0DD9C3FDA5E5D5C7A6541D3488128DD38CD5EEB5D0F975754BE4C4162A42F604DB252DED62324713B21F9524CE2B1ABA2BC9884484E0A84D242CFE51180EDAB3EEE9B8D5B48E24A22DABD85F3D8925D65F41C7AF698045DE0233A4DD4EA09FD063DF2183D099EEF292C41D3488128DD38CD5EEB5D0F975754BECF896CE447FBCA40A2B448E6368CA0AEB9204E722D69FA901329E8557611DC9A360932A431FFF809C938B39FC061E1C5D3899DA134082DF39BFADD04C11F8505AF75059998BF393FD67A6048ECA298BDD486216F0D429348B803B35B3224EEF79867468E727ED4DC4B0F11FE6DBB14148A1771EEFBEEE909A0DFABCC647AC020E34AEA4D85725F7144F41B2A2A1B39C49ACB906ACEBA8F3865EDAC45B976392CEEFA22E7C1A36830A77F25DAAF01C4F3EFE18BD34A34408A4057BDF48736109A01498DBFA676613FC0BE57673876878FEA8667AC8FC4C178B67F0E1EFC5E9F754B798C11EEC63A4633FCF017FCFDA0E5E02E5314EA0EED92B79FB7EBB9E42CBDC7CA572E9CD371EB2D26406D38E84895354CB8FD5FE9EC11DDF4A8877D9A9EA835A93C86B3AA7F86DC16EACD64EFD0A6721F5F5734EA5EBBDF2E59211A1AE390A1B7BFE9E65EF313A027D21D0D7A5248E0F3F91CE85ACDB29EFB20ED5730884B767ACFB56CD4E7961A9B794DE8D9A003DE7B01946C783B7754F84D0B8BDB6AFC7CD8EDFEC276205E199C18B0A527D8E99652F25F773FE75283DDEE229E5A1D8D0548A65E3FF8822387585C7AE2FB9ADB973184627D5898A10345DC161118B1911621F0D62ED4541175D35916907D0E183BF4C9DC33B5DCACAE9EDCA97C4FA54C197D44F48BDA5B61D7AB26679D53878968008B26779086937779560E95DEB13CC293470256BC736B46D72B1BAAD0EA134A509BF7B4124B2D8236D755DC39869CB5E5DEDBB14409F9914670B22307564FC4FE8BBBC65D11DC8DE9062673001D63A0DD338357AFEB044A24051782891B93869A5729959B055EED453F2BFBE82589FABD7CCBBDA72E1F2373FB24AFB792903A814433B290CD32424C9B871A6B1D2714D6E7FBC7CAD12595D1A86E06D924B0C16DEF82412FCA1FC9F250076E2259BED71B9A6D8A5C11F20D7428CB65DB8CF16A62586343898045DE023288CEEEF3C9ADE197835237C23130CBAE9F66F2CC9C2E3E4E15871E22EC2123CBD85F3D8925D65F41C7AF698045DE0238608632AE37689204C71CD8035DFB78F585E562D8827DDBCA13FA8B2B87E80AD094DF3C72E5C03916681C066F12145B679F1E5C55432B8AF2DB2369EBDE6601ABD85F3D8925D65F41C7AF698045DE023DC08C3C37E76D836FF328381F4B5A2E5761905AED4CFA256A99857AEB8EAF2E0BD60BFCA19B5B8C7FB0E0E0DD77A9E18BD85F3D8925D65F41C7AF698045DE0231677ECB898B405635530D0F02309DEEAC68F61E1A9AEB4431DEFBE22E32BF3B1BD85F3D8925D65F41C7AF698045DE023760BFEBD041BD83A573E494A0E7B857E9EE372F823A14B3A2526A14CCA952EB1024106687299409AFB1B7644FC67784F8960D206FD9CC48BF2A6D4AD386F0FC3BD85F3D8925D65F41C7AF698045DE023A5426D8847CCA7224FAF3C1EB2B7E97014F3C34A0EDD728AD3AF6564A5BCBD47BD85F3D8925D65F41C7AF698045DE023D374249DE91A7A199D5EAA13FC9BAA81AC9530E1A04F40B1E22CE2B653911DAE60F96F5CDA3A6358FB7D295DD8F2A0C8986265C54F4F37F307F1A5E2B3774B677017735379BC355C218215E37C6B27949E311978DAC1665B8D5DE94806C1CDC5DB00E1C19BF21B1EAE681AD2BE3E6BF4F8AB6F3275F0F334C06879DEC1DCDA04759F7B19DD7B35062D9D0FD0F73DFE53DC565A831AB75A896A6AF13D723D5D208653D0ABE44AA5EB979F0B3F8852C2E0BD85F3D8925D65F41C7AF698045DE023B4DEBAB9F106AB9F72FCFD2F75802472E8DF348A048C4C9A2A89743D98CDD550A97A3046E31A63677F701D4C12682671BD85F3D8925D65F41C7AF698045DE02328B2CE2B6C369AA808E85C0BD0878EE9E56FA9532B393417B1C28197EF8CE2DDACCC7EA9326BB13E84C2213CB195319F53AC67B4AF04E32675FD526A4FB9B5E0B0684C40E2B3EB76EC56AA7EEEDF8B0C8E0937963DF293B6B167F628F9EEFA407B9D0F092807159843163EE1CA439B2FE2036FE5929D4D9682012C414C78ACF335849D86FF31BDA855E3AE05F74C44E34171690B530C8394EE450C405737E519B4FC024F9BBD3EE74972579BD17CDDDE759F7B19DD7B35062D9D0FD0F73DFE53024106687299409AFB1B7644FC67784F681DED9DA336EE010E691C10B546A4A69EBD9B3D211A5B6E5A32FE7EB2F2D4BF8A43090D1C42571C272CDF7C8218DFDF32A5D5F35BDCB11C2885E5D3C5E4AEC79BBEC3A17513DFA999DB7BDF1D5D1C3A404FAFED1AD507F84DD0BFAD71803F714D110644BC3A1C19A9029E8CD072D375DB7C9AAC1D910A11710C149BD9442E42F679DABEB700EE8DA9C55EE59C0BD11EF24AEB2DB573CD57E202912F272D31C2A4CB7A83D4D0918273667155B772B1B7F9C7A930FFE44CA1D511935B2E4EA6FC53036DB581FEC0BD4B8FD18E97F03ECAC992F29212F0015EC004720164456226E8BE0EBD2A5A7427AD2D7E2831A97E22759F7B19DD7B35062D9D0FD0F73DFE5371889DEA8057BB633748593F66E935AFB6343D3E7B97673604BE36BA2514946A57327449DDB8CA356102F13145C96C43BBEA305B4873467150E91D2FE99EF600F6471EEF504AB6EB077ABCD60DEA4FAD222964804D8F397C88BB3CE203C3FC50DAA28221C7309A32767C8AF7A3F6BA51F13EBECB51F56840397A7C9A50EC1D0EF9EF056F5E03A30E8DE717C644B373320BE2EFCA599C22BDD3F615DD1AD1FEC945FDB9F48E8FE4EFE454B767E821565E23724AD3F764858AFBEE79EC225F51F648A305ED92AC2A5DD137EA1D3A71F004D21FB8E69DB0AFA8ADFDC38FD15B7EDDCFE7435550063B4EEA01961219DB08B4D76152F106A659232CC1A6056CF73E03395889BA799A45BA4423BE3CD263554F2BF9F13C0928AB30D1DA6D5024D4E4784B3F93C134E2D25B791526200914A1A5D8EBE951DDE59FAD584E388B1E755051A224C1C7965B75570FC34EEF7E4796873B91A800397F9637BD38E4D20F45B7CCC6C632AB9FA884D9043639DFB99494C7AC76BE8C479DB11E92327CE95C8ACD13960ED28A9C5C871E074ED2E6DAC9A3F1A8CBEE60571255D72C86719F4F6EE4FB8BE64AB8EC7D7C09BF4D5A5F1C8DA9EF7173C5B91D776E975237E1D7B88C7A0558D76BDC1D3D5D76F0DBD65F7BE108351C98CC79C8AF50A0DF2238A338F80FA6421D1C6D372B97A0610859AE220A2149AFCF6458F67F5C7538077DF91A9BB08D85CB4B641E0F2CADD953EA3B2AEDC5FDBD85F3D8925D65F41C7AF698045DE0230CBF636D894226D96BB15AEC8D8581D241D3488128DD38CD5EEB5D0F975754BEF30E367F33D164D0E242317673D7EE1DED8B924C1C7ACDFE5047E7FD40BAD6C8759F7B19DD7B35062D9D0FD0F73DFE535C89EA76B151569E06AA62A383E1E794693D3AB25234B6FD3C25A85888D2285544C13BED311020D41230320C4A110756FA1B63E371AC3D46BE6380A6FC6E95AEB07C08443927543C3055265213C8523BC6DDFBCAAF7B1BAF7AFDAE23D9882086203D0B9C81FAB4EC272DC4F9EC3AA56F0EC9BFE808C9B1232ABF8E0F74FB4976DAC111B23670A043C101908F4E7C7530E081A657771B8F46FFDA056529DBFA1FDA9C43E69CEBE71071C4952357E8DEFC4496495CC0935CA4856EDEA2C77657DF7BDE514B76AC3A5B01EBCFB6533C0466476165ADB065C504C27A8AA26688CB04C577A4AC3B53C59BBBC1B505412686AA69F496286F6A3CE9B8CBF9B0F1A12B971AE6F65CEE1FF87F5A66DC7807EC371824B9573A6182E5D55BA47463283B1FCA7C99633638E03A0D086FD4D1A2FC87AD84799D786AC319CA21E30369BFB0F4B9FB7DA6E4789ACF239456B494536B115EDFC2803AF64639368DB0D5ABC8EC760E476165ADB065C504C27A8AA26688CB04C577A4AC3B53C59BBBC1B505412686AA69F496286F6A3CE9B8CBF9B0F1A12B971AE6F65CEE1FF87F5A66DC7807EC3718D2E1BA0DB6CB447B7CD0672287A43E1B57DB829D748C06C0F437D2B9A293F0AACCA82E3C3D3002DE250BD5A35953B888A84E82E82BE4DC8E22EF93AB5DF8FDDAAF8D73399F37851C3252C8B6061D7E667F0806D16F859423F7433A7F98EE82AB2E5432CE4427FA70ED00FB883E4C184655ACE5B78881613F26F32C35935B79C0BD85F3D8925D65F41C7AF698045DE0237419C09F9676AA43D79028C0DEC9AD0742EC7FCC9795942CDC86FE20471B1DBECB1B7B1F92EA800C713649217D4F317E2461DE92D29D99C2EAFD19A2E9529013C992F29212F0015EC004720164456226BB0E0BE6D697E7908775917F6C3B5FDEBD85F3D8925D65F41C7AF698045DE023657E973D8722D710BCCE37CDECFD53EC59505CD6B969079E1E39C0064DA05DABB8323A4CB163F6A6DF0D90AC76B41256F453E2823D3B4A8F23645DF724A39B1682879F6C8855D6B6452C76F8185D0599FEAE325EE7F5B46C944128DC6BDA672E8429294B5DC011B4CC7574ABF543072258B3CA7A042F273F427243679A3FCDE953DECD86FE6F70B57324D48DE02BDE6D68C7C675A93927B1D850069FB130B55FD6CCCB7DE7247E665054746453CD56938AC06546BE2FA76A366FB7E5AB85754BAD0544787E385F280DE1A10860D7EC57D4CCD396FA6242BBED714331553A5961CC8CE56FC74D972FC9C0E63E139DE643D3D648DC7C9FB81C1DAED9962A849A9C4A8886F5EE70A7B4C2E4CC1083DF36AFC5A0A14FAC3C226D217D24016C20D462DAF6B8C577A1254EF99B491B1FC9CD28367D08DD38F9759EB0025B1D8807160CB9511ED601AAE8BC200CD0D593EBE83F47DE4527A4397B662DE665C4870EAA01EAB13B939C94C1D39790D6744737D1FB6EE4297A6D67B30F79EC5FBE71D50C55DF74E78765B6311AA4C6A1662B1E42988CC101E8D11925202B1AF5AC871D777756FE261B1170C22F2B3405962A0C29A26BE03EC83881FC122E4FD8C50022894FBB0CE2E5E99B1AD8B3567BC32575D3D82E8F3F32AA0C840644CA5F782903F713CAA0679031DA54FF85F24AAD26EDB5A5907633855F4FAB6FAF9C3401B4716E7C84848D026628B0186902E484EC4C8DEEC0EE221B6CD13F94F616E9F586CC0F8E90117FB8FD1C52A8E4514A63E55311C9CAB37D0B523CC14BAC61076E12702C18C9FF2A87767201525161948249861B9A5380A699251028668E5767EC92363C2081F2DD53EAEB9E13B32A37912EF3968499C4ECAD594E6B1D3A2894415844E2F34608FFDA7C44F24757104F87143482C6759F7B19DD7B35062D9D0FD0F73DFE53B58E1F57E04FDD99A8277ECD7A7D9EEFDB71C800DC06BA6B8908B170CB5D5086BD85F3D8925D65F41C7AF698045DE023457BA1CBC1E07ED5E4DC22D16D24BEFA9E76B607D6A24243EB0C3D2C2AED1FF241D3488128DD38CD5EEB5D0F975754BEF15EBD1B624A75CB701A85BDB56FED4DC7D60EAFBACB7EA053F4204C7A8CEC8B2404D73C9A8A4238EA0A0469FFEB1ABD5CC0EA7E984FB6B6097034F5ABF49305BD85F3D8925D65F41C7AF698045DE02371BE420F4351456D183F5778DA9D5286A6C291038E30E1D72EC2B46B20D1D26EF72C0C1992F409EADDF0CF22D29FEF3559C2654E9E9606156D4A8AE60F576C960F507C77CB239DC882AFAA744FCEC38F99CE97F431E94D6ADB5ED6706DE7AE078EDDA4642326B8ED0405E378D800C0521D9BA3B2450F59BA0D4C93B044443156BD85F3D8925D65F41C7AF698045DE023731C037AAB932BDD08621CB8E083C41F400245F2958607818CF3F04F9B918316F7227844DDF94D8452F901A3D39E2E2ECEB7A0FBDDE3517AD09F7F4D7682A38EBD85F3D8925D65F41C7AF698045DE0237A8644A9594A0F9BD4CC49CE2D88C572D3CDBAAB53717C5E34AB42CEF95908E7BD85F3D8925D65F41C7AF698045DE0235AD504FB238FF216D8FC787220B130D207927D287418A9E61C900241AA66388ABD85F3D8925D65F41C7AF698045DE0238E2717DD847F5A5928BA2090E83F09B192B1F4120B5CDEE818337F06A72B3E91A23FDD80EA7A59FC2C21AF3BA8634514308E1B16488D3DA40AE33702E789F3EC7017735379BC355C218215E37C6B2794D1EBE11F548D44077CC2C5CBE0C78EC999FB6508398D43498FDE8A7B86E1A5336C5CC08BF62E5E45D1668BE4472ADDD4BD85F3D8925D65F41C7AF698045DE02307C52FDE9214241B5CD6D7520E7CD64333BA36091DD6950ECCEF0C7218496808BB2058EB72A17509690DBC5F93CF8FD5AF084CC108488E8A04298B1D7D7623F6BD85F3D8925D65F41C7AF698045DE02333C4C97C4E7DF8C73E05681CAE93A112D63096C1A71D0C434AFBA029B3E8A61ABD85F3D8925D65F41C7AF698045DE023EDEE89C5C7B475E37E6E2EE0ACDB2D8C1F831B543D81701882F78ABDBF742E6FB7EAD883F2EAEE3005E364A772C0CFD9507D5E403CD27A7807128F934F3DCEF3FDA019F6C565A99A043BB093AD34EE8985CFF78963BB1B3C5098BF1A93DD1C41BD85F3D8925D65F41C7AF698045DE0236EFC4A24C399EC087CE89BA138D0860D531B95C868AE2425A777CB68F73DD308A900C576F5ECD4777EA03269138E99D56D8AF454716E2A218094DD5E7C7B335ABD85F3D8925D65F41C7AF698045DE02347B29D92E0021D01AE2BBCE9603DFE3EBBEA305B4873467150E91D2FE99EF600B201070A90A36E97ABA2959C665C1C4AE60448634AA731659BA49C8BE563007BBD85F3D8925D65F41C7AF698045DE023BB44251B0C00A9A22B0E8E0E277F5C150B9E32AB7E484F5CB1CFA54AEF901771BD85F3D8925D65F41C7AF698045DE023C2C749692E9963851F071F6BBA1962AAF6887DC5BA394DB9123145773A02D605BD85F3D8925D65F41C7AF698045DE023E481DFC1997544BBB6A7576C104345A12DAC53A86647442FEF898FDC18E45497D521248C4167DED76F8BB089093E6453B1AB022404FCAA7C8A30B2B4DE446606BD85F3D8925D65F41C7AF698045DE023731C037AAB932BDD08621CB8E083C41F400245F2958607818CF3F04F9B918316F92E9F0C3CB68301EABCF963EDA46EE48990B4C3C6FEDA59669663A701B15E970F14184C0EC1FC9D45DF4452FFE1789B6112F02CC76698AAB05636E0DF529C309F5F8E22730E0275D86262EC265DF75DDC68703F4A1FB97CF47225A98BEDC0F9582F813E21A94C4F464FA8647121838A5D24967791F6BC8B38BE61B855ED009569B689C183824F549881CA937ACCE88331268EB46AC963703107B93E5474E1BD0210BF5152D303BC0DD13B2706537AB3288FFC70BE7422F1E4CB469CE4352893DC16DB766B8465FECD103E351D7CA1D39B2CECA91272509C45C0E81C5B8C376372BF8133791DD7EDA704362449E21909FA7A88D706E0300A66B5C50C51DF2A9BB33B38250BA7A4F19BF08153B5B05DE8C56CC1540BAA4076ACC53CEEFF757DD24EC00CCB74897B1195765BE8F0744D27E9A06B1605945808BCAF15C34E9552F875ACC2B4C817C302DB7BC5ECEC9501A4AF084CC108488E8A04298B1D7D7623F6F77615C815EF15999BCD7377087ABFEDB08FD5C7BFD2BEBD6DE392CAD75D5454F91B24C233DA85558A5DBC06A31EDEBDE51CFFB1DA1320F0F0096B6081E76FA81DC6C729A70A659CFD95EE60C4D02724E1A29EE055EACE1B9A37E104048C4213371F64C719EF1168DF6183FDE0F20F0B2F74155861B799E71AF03CFDB7287F93FDFA3C57C440EDC3E9D1D6B86B800310D324C796943943621D0C2EDB3C654A2F6554F02300DC660638B80081FABFB72565035A6E8A8D69B9B892FB491F74F5F826C58893F1ADAF23CDC390C51CE7AA1E25BDD6AF9D4AA6E2A47DD9219764CCA16AD76C9679F454D1A1622BAA86E5A038D47C27B3431A1FB928AC56C8F88D5DC3E6BE6560A2B524CE52B8930FA12DFBE4B3B2C4AC300D6C24F09B40DBEBCDABE3A17CB9CAC0265A4D43B5C670331DD381EDF98A462C2E02F59B51BD15E2D91F7B1B2DAE93BE374D0309AEC6AF508A4A065C7A3F7D14E508876ECC06D7A68A34F5548C0FE2102C814400EDE64B7F9659E3FF3DA315CD3D8A9A3BCC451A582028EEE34F334FD3EFA774FC97C178509CAAD38FBEA760DB663E53A947AAE9A457B2120319E9F3D85DD98E77D8C660707E96C6CF10BC3DA96524B8D770B3EA373CAD258B24E5886ED9DFDFD2D3820EF3A31D8C6A51C985FE627D9FEA1BBF6548ADB5A97EE83CFA9CDDAAEE250BBA76D6D3E21E903DFD8BCECECAD077C1BF7F73449403DCBD1604C9870947FA5D5A176169CE9C7476B348E6BAFA431FD72724EF1150B031EAD5CA64EA935BBAA7FF5F16D996DA5456D29D9121E3C904BC1D296F106F24AFCF6458F67F5C7538077DF91A9BB08D6D463648A4A1EBBA7C8925A1C36BECF664A603DA159CC8232A4F4ED7F0D5020A7A8232CCEEAC73048024F926277CD8E2847F1A6F4C1ED12AD01EEE00C49FC2F7B1B481D6498FDDCF85A19F9B954F5C225A064A159E5F07938C59598A4DEF868EECCC3391D502F21DBC1D578E9968FC6572DC548862FAF1FBB4FCC022930BE351F5CD945D20E33CAAD72DD7BEA60830214E4D00CF7BFD26D8E5F640F41B211695F7C9F78B4DA8ED5F92F9BE45020D0B3737FC54B92D8A0897283EB15D3BD5BEDB8FB39E72BF4FC690F60B843DB3CEF5BCB846E094C24593101477EE3DC253D935227D470C0275DCDAA536D82225919E0EF25BB4ACB0C655AAFD35EC4E81DF94437AB695DA3248FDE53B389A0959A5271F39B738204F01E303FAE6CCCDFEA0754063C509AB8A32D83E01363F9F354D36EE9BBBC7943CF61D113DC9DBDC4AC95B2542F52F3113A3E11ADEFF4C9A26EA14B3317BEDEC200AC6A044B9005D9DB2688C64A3877621A031FDD5D66779E956FAD25637D089B4CAE6666F16CF9EC8D0B00DE1E3391D0978C75EBFC2F684D0C5224650A546B0F2D01C02E8832520E441AFB92AF5C7FD5CC65016AA8FED447EDD70C631D8F2AF46ECCA3401875F133679CF94E3F47098A978E4DED047535A267071D5CB1B7B1F92EA800C713649217D4F317E7BD8448B6835D6ECB0F6C6B7C5A25EC4DE66B76B5CEA65D91A8BF9A957D005DC58DD661BA936C2C202629EFDFE47AAD7E27AE871DC506D0FD2EC0645277EDD0CD5555C8DBCAE02B2D00F31DEBB24D8FFF953797E67AF2D9D6F82EE355D5568E2BECAA9FCE153FBCA63796AE684F4CE43066F9E480BBDCA1B255AC2A8A7DBD2E4B05E94951DDF21D3DFAD8C976DC43FF4F90A76BF2E9A6A1E07C8DCD2D5CDAA22EDC920DD1415604C47D7C6855E3D8BDB5A3BF83117313B9CCC0A64E0A1388A8D1685637B8CA991A412315940079E167353F31B3BF394597A2754A17B9F79796739B738204F01E303FAE6CCCDFEA07540CE49683653466D771EE37E772A3E91451525F505EFA825C12AAF5588231BF96809F79A76AF1E0C186BC35A2D3A182AC504FE7AD798EC2B86E356293F50DB0BF0293FD44A581075EB2DCADE1245542ED43A6F04FBC222EA14CBF07ADB1B83D7464E05EC557877887B17C519122C7A5A0D2513E3650EAB6658FB9878F9078D66628CE0562BB9A8226112F84B7CB8A94AF6FF485E769F7AE4DF199136A87CFF064F10534B3D5B7965C1113230433D7FC469AC7AD31CFAA8BBA9872B6B3CAEF4B178E769BE1058F29500DD0D8E79A4937340C6C632AB9FA884D9043639DFB99494C79E76DACF4DCCDA25931FEDE2DB964CF1740AA49DE0126098ACC43877F0D843D1165077DF8798580D3C8AEB1C83AF154BA6CCFCFDB805368E09B5443BB02486F8AE0C8310DC4D990EFCF6B12DC8451DD9BF10C2CA22DF96859C7BE3C7D885386CA8122E06E74C15B81E0C6C508A26CFAA8AD89B8B47DE0E0A27E61277B1E25F0ED66DE000534FDF2E5E8A054DD6AD783D7139058D747394FBD578E389377F4E9D899B2B07BD964CE6EAD55095971E0651851B931106CBB2C85290EFA9FC65DBFF2320C143A4D5C5822EF92AA89635FB450B4F1ADA4A7FC6AFB6F6B0BDB4DD0308F90B1EAD040E5C8B9E2BCF7B93DC4DE09020A7DA04A1F1BD7F2590C73FFE385298B77851062FF7FAB906F40CB60865D0D5BA58F0B3E5BB7FF655F5C9B50A0C866377ED8205D3E0BBD7D6ABA87D6AEB9AB5B23B8C482F684EFBE72A4DD0E7A74BA983332CF6DC9E35A7CE697D223134E764A3877621A031FDD5D66779E956FAD25637D089B4CAE6666F16CF9EC8D0B00DE1E3391D0978C75EBFC2F684D0C522461375A54C1D9EABCA85A0AE26D5A0AB5BFA7A88D706E0300A66B5C50C51DF2A9B408A4EC230AA0968CE5F4D689FF80E64AA8E6F81CE43760AF675B88F3C71EF40A99A3294DAFFB6BA8AAAFED71D6926A860962C4746E61DDB895A30B5615DD7C0279E5D19BAA6003EA65B21255A914EFC11EAF1AFFA25518BF79558F09CD6F55B0D83987A102361FE52A3753C173DBD78E041BB7CDE4F03823D5FE6605B1DA4BC7AB6C63F3FB048B6F9893F0BA5E4F0FF6D19D037C68BFC72602B2201279FD471F43E3500ADBE2464B5604E1ABC1C7635B01813CA41590158148414B2F8B1E4E9B8D675ABC9E2E1B54AB98EA46557A76204B046B578027E36FED32CBE0E7A8AA6221B4520461EEC3754A9042BB3041B069DEAB002583B00F05282422F4CC077300044D4D197D7DE79964B3BDB616635B6409F84C013F39A4C9960D68CC250D734523307DD2D1607A380424E47B4719D68D59F58C0DA3995E356D51ACA07DE88F5EB801C39880C07B906FA79C344B1634C983F453ACD4A7AF2FDBE2EC6F5204B8AAD0C553AA2F2F9DFC5157314C48852AF65C22B7AE7C6BF2ABF1B1A101C6D51C44DC97EB404C1A7DB1771C22386224B6196031A63264E63FFA9BEB65DA0D651FB1606BF3C0C5213A7E108344F412F4321269C46F43A9015448B40A0ACEF01A0CD060E2A2A970F1C4195ABD8887C6A3996C69D18847B52A52D4313131F9FD45A462E08E8D5A469BF2BF41AD323ACFF62F1738709A6DF227482590182BAF6AF0FEFBCBB8412125A448D84AC10FCA2B122C1C8979B815ECAA6B9A67D55773FB6D38239EC2A8729A43F15A9E21CC0D27743685C17F3F70614387D987088345F8411062A31967755B924CEC6D5CE1277EB38679AF8AB14E40178DC26A11FBDA5D2CC1FBD85F3D8925D65F41C7AF698045DE023931A78F0E31D1AADE5C9A2F67FF80F9BCB1B7B1F92EA800C713649217D4F317E872A2AABAC168D94FB990090AD8944DBC73D68048590E547A2DFFB262E8FF66BC992F29212F0015EC0047201644562267B783B7F0CE2A574258097A4A43575D08DD78FFFCD1EF10EB50AB7FF8C871A5EAE4157C35108E4712B285B44265092C1BD85F3D8925D65F41C7AF698045DE023AE418E1866E3C704469A1497FAACC04880D2A9E2C03358D7744DECC217C7DB591A5F6FDEB8ECDFDE8D28FFA7AA4032D48EFA8FB37536B500E19B703E0FF54ACCF2EBAA13C4EF5566616C6029FF671C8D9E8BA151FF293C863DA15F91E60CB6E57B8759144BB847E7AF6BEE0821F45563960ED28A9C5C871E074ED2E6DAC9A3F17C61A3F8BC4D8EE6A063BD7D50B7B248B6343D3E7B97673604BE36BA2514946AB05E94951DDF21D3DFAD8C976DC43FF4DDDDDBFAFC1A5B06C81376AD32BD4E7164C6680C875294B6DB0171DBA525096EB7F2A5BE3188BB2C548CE7DE5D9582479AF8AB14E40178DC26A11FBDA5D2CC1FBD85F3D8925D65F41C7AF698045DE023931A78F0E31D1AADE5C9A2F67FF80F9BCB1B7B1F92EA800C713649217D4F317E872A2AABAC168D94FB990090AD8944DBC73D68048590E547A2DFFB262E8FF66BC992F29212F0015EC0047201644562267B783B7F0CE2A574258097A4A43575D08DD78FFFCD1EF10EB50AB7FF8C871A5EAE4157C35108E4712B285B44265092C1BD85F3D8925D65F41C7AF698045DE0234275C5F2D8E4A0730C04190836651190A35617E938A4937414E013201A0068AE1A5F6FDEB8ECDFDE8D28FFA7AA4032D4D470F24B81FBC5E80FC3440AD1D09692960ED28A9C5C871E074ED2E6DAC9A3F1B4218DE3ABB5A2B2243DEF9C3253E12A7E230B6CA9093101768C651B95928DBCBD85F3D8925D65F41C7AF698045DE023E3DFC3795682788D80C7821AC3F21F04A5EE1FBAC2A654815A9A1FAD37AA5CA149659AA7C12B243F1F4132BD7AF1FB34775DC4F361034EFF791874F5AF05CE75C490BBFB69A97E8F0ED644685168694A10FB665A2CDE93163E6108553A931CD69A70F6B1C2538EE232AE5DB1095FB3251A35540C69A83B21BD1809E51EB6DC6024993A05CF866B25DF57DC770554C33B27D1410EF0F091E41E57EAC5FBCE09822813F2E20F19CD10D45E6955DBC483D6D4BEFE477C9F9457AF1F5681559C0C4199E0F2FD11EEFEDE456ADA7C081E4862E7EF1E7936B727CAD8622D2A1DCD4E4EB1B05651EF4C7B8CC769CE1ED0558439DCBB6E04316E4B11E55D91E39C20E9316402B99AF222D8358C157769A34CD06961D401F059B7E1FA37CECBBE807C8771B1712F44878A89BC5634DC8617C0BCFCFB34A4E9C0473917833D20CE43FDD1A585EB485E2F9ED4CAC7B64A10481B7EAA3A2B2D1F699DCC15E2E1237E83821D723766DBACA37669C9DDB211773C796138199B231E12DD6EE9A27298EB4817AB0C48BBE8C9E276FA9620CB804D6E3C869231833DC70EB3C4A34AD9B1087590ED2C88842952B47AB27A42C223F162630FFA855048E09A50EF76A317BA78C47643FF8B4B3E4316C9262C1A52E5DEC0D6AB4C621DCE0C89FFC95A5ABF77269D82C06BA32010F28840706D80E448FCBDBFE3241DB527128FA1C7AA36D95C093CB9C928BE348830813177413A4BF9E6C1F055805C5B4623B6A9D281CB8AC736BBE784B867977269A62F83C698861BEB8211995A826E2B9CB27FEB1EB18732F13392187C4F2BA835217ECAF1E7709B74F5A694FEC3BAC37F0DD2F92673CB4720F2BEC17F04463F7FF14771573CF74030158E45CF1C0D7C4D0C921C1F77DC462708141A2630B2E34D2748597E6A6D7EEDF61E36F242F6D0EE18114EC1EC0E0D68F136AA18AE9E7917696DC41A0B58DE11225EB88B5DD639F02C36C4E807E3B1C6576F40EC0A1A549172BFE88A373C063B7B6387CAE9950CC1E3F071D1293A4647A8B03392A709068CA110B8D9E9504069C572464232D3F336721D31A3E002FD03E029EF70A85509BBF01398803B36EDA687D2005E9D86BE0C6AB9323068BD44DB5CB174AC049A2B439168E80E9A8186CF54A2A29ACF8DA9853F68C302EC0E721EE74F981B2C57F1FE016F326465819CB095FA3A4E2D921930477E4766350AF8492C5918CA01AB7CD408726B48FC8D2D01F61C35FB582F813E21A94C4F464FA8647121838A10C8AF5B08D833BB6F0F6D92B7ADBC7CFC91D2C1248F2F1A257912D631CB2E893BE9FABBF170B53DD1CA5ADE81B2BEB2414562E593683EDCACA9AD34DC4C9CC7BA67799E6658F78A57BA9823F78438B6F2E412EF8F8EFCC01C25ADC166E6E4535B75A70CFAEE3767551AE63DDF61FA3CCE9A71F381F5432168F86140750DE0262A282ADC67D9DA4D42292C5B03BDD0969DA877750AD6465328F07568368D6320CDB97CA80B763D17AE4B4BA26F765AD017987E7F1681F0570D1885D1B1247DC5BADBB59F582C4EAA34DCDD7C2CA6288D21B584287E808995661491E44B46408C118E77C07AD477F8979D40382F1AE0C1451D020157299356C8F2F6A8711C3D4DAFEEEE0ED28C521ED683ADDB303C4766980DF45226652F96909C4B758432A3317A869B402C94EEBE51F4BD8C1BA3EEF6D0AFE9E747994CDA68E0D96869BA3D388C2F3D83D7BD1A3725A9A00281B60F7B9AF8AB14E40178DC26A11FBDA5D2CC1FCB1B7B1F92EA800C713649217D4F317EF470C298FCCD413864004714241CB3F7EA5C63B57192F63959EE1225134DC25369D07092AB41EBE4E365A3A22EDC2343FA20DCF993F4B2A01874901FDA1E94FB7C8829A72049C2926100642F03B06371D3102223C9C2A17EBB617E997F60E3121750E8801B67D29ADC81CB86B6C925047FA221B685953167A5610CB2E2C17E5D1A5F6FDEB8ECDFDE8D28FFA7AA4032D485D1F79E08F5852454F6A905945DA324CB1B7B1F92EA800C713649217D4F317EEF5320088E15FE08D9288020B9497F4A0D4D9B56E081C6DCD205737803EE07FE9C230D997FA678B5241577ED601DD857FDCC3ADE31BE956502ED15E892BE6DC2B01813CA41590158148414B2F8B1E4E925F081622DCAA176B556DB01C24B503681F9D4F6DD2E461B9D2D0062052F31CBA6C2ABE8613CFC66873CA00D6ABC373B5E7B48413928A658CD6B55126C751F0D68612E1B7DFFEED920D21208A564A8F58EE6EFBD4DA1D5F6595231F86F7530AE11268657C45E7954248098A313D398077DF0189FE06D65F74C0F3189D9A9AFD2BAC8CEE68E0189E5D791F90B472FDA79C1FA19CEA2A5C2DDB1E5659DC81C6209EDD0C2FD3B72763AD3B232E21CA9173A34C568BB69FDE829D4E8E67F68F40671616010BA23E25F0776F37A6D55A5AB6AF56D73F11A63B6CE749FF06C7034F549C47BA9EEB60991471B50BF41CB21EB9FF2C2ED8DA2968D9457A7F8465BB7B93C7D92158495DEC56045E6E66116B89A97EDE4B8B59376425431AAA4E185C61BDB14C1067A63B97503917F66248CADF876D62EDFF4097E54FB3B06526B1026B9A598E65933FA9482A2D78E15B75D824BE477D5B867C9D9917E3EB1AED55F16A8C30EDFE1C818A5CFD5FB50B1101820408F0F41C85479CAA593A2C99DCE5F5D3031391046AAEA136FA2DCED2C8B1A37954DA1C2B8935F66E288B9565C16E522A55B7B08C4FE02684C7674D6FEE2F6CC9D0E45AB9038F605ED5D7E8D48564147B211E436A1C0161A03647D5347CB2AF8483F44C3049544AFC6528DF904577790EA0CA91A375F048D636EC65097CA3A0A5E0DC9C807513EF4843238B00F3ADC3C4B356BA7CBF2AA1C2A0645F448F5DD59E8C905DFED180FACDAF58EF98C13FD7B13E41CE8F9B15EA83959E47564B9EBCADEACEAB0703C051CC3AB3C82573C4550315977D0ACDA15424FE4A70643C2D2FB71E589512B725F5FECDA537441823A043CF97D892EF7D93E5B6AD0516E253971C44F8F57211A3EAB0993A396D35E48F0C8C530A7BC98F8BA996CD9104F27F77FBE469C93589CB327C8A91353B4D58C23A6E500B8921BFBDD96ACC2EF83115B908A79A0AEED4F658496FC58B23CFB37C037F7708DF8A75E83AABA451BA81B9C4C879491BAA00695307521ECC350CB613B3FB3EE65579A31CE4933ACEF0A2AA4F2B5B18700DF3B5A7CEB49620D8980FC6E87CC2C0F62DEC7BA2390D182C363B7705F20575DCE8BE076E8FC370FBD27BCABA911547D625E17A95C49B18F50F5F4CF898A7C965A5667116D82A7A6BA995BF28912F20A2AA4AD643535DDCF1A7D2C5D8A651314151839258454DE0C090D0FC39829CBC4BF341A68422C45EFB9341A55DDE2A2AE27388031F222C3B5B4A150073F2891823AEDA85183A377F41B2CE771A0575F2697C8E41791A6CEF8710997CD12F6EEF2221E3EF620057E561D492A2C3ACCDC17646A23A57C0908CCBEDE03E75BDB0E617A768ED2A0D0606B20806E888A072D64C61F14D3723B576A5914726FBA14C33498F5A533799F31531C04408900022BB39F43902613488A4A6CA90685E41CBACF34A5179CF78824273CC25674F53E8CD0452745EB8F61218216D47E070D7D514691488D4B78F38E77939BF428D679C2D9126485B9E3E2D3476EBDC8F4938A2DBF844BA74574D11C0702405E64F605F2D2ABF08039740D6BB63D1A5E7B14BC928CFE05CB2B10CA22AEE3CD5BE398C165827BDAD3C06147ECA0208E7E13D8D1D72E36F24A01F3C80BA9771725EA3F0C9BB5CCCDD152ECAE9E0FF4267BB737144DDBE6EB336F86C0AFD43E36C871D76A8CC95124FB0D3A4045DC549BF3DC455088DB60449608E1E350E88D7C077A44AC432429DC9E073225624D3C0F98EDA881CEEC74A98E6034E6EEFA4A0F2BE4B2B2441429022BA321918DC48361CC0765A4FABD160F915E51E4719EB162607AA2FAA7F15ADC317788BD42034F424C7F704E103A030FADA8103093C6601121DB695C8C466C0D87A2E0679C42F6130AC399F5C3B295BA99FE4FC244E35D3632BDA32B5F28399BC82001A0A765AB80F2D97CC73EA97342E165F9CA8FD2F1AF7473EAA0811972A3894595047B883EE8E9F8129F2B3B86D54455DCC3F75683166AC65417598B33DB9BC823C63EC7F42009E2E3449ED1794D4B22CBB62322C19785F841C3514D68D259308E114C46AB03F133BA8C2F4F2F92D6AE6DFA7EE1327DB2F0611675CB4EE87E569BA9BA3E8716E5DD35BAF205E259CEB7E48D7911545FB07FB516A0A8F4426F9C1BC6E1BF04B73CB6854381E9B295A848A9B6194A060980504AF0736C905E57A321918DC48361CC0765A4FABD160F915E51E4719EB162607AA2FAA7F15ADC317788BD42034F424C7F704E103A030FADA8103093C6601121DB695C8C466C0D878538EBB5B42CFB7ABD1154B3329A077DFE4FC244E35D3632BDA32B5F28399BC894900AC757E781176C8C0A386A06A290211BB944F4CDFD88F7E7D2C35EA97B25C0B0537C72BE7972E0100D90C36CCB4344CE5A0D0DDD48CF43E64B4F63E2447E30611C4F031FCC3AFB317528C2A5E26171006C412E79536D51719722A20FFE96BC8FC855A00280CFCA1C8B5CD9B023D0E76A28997505C3FD8C9AFD76BA39AB9FE6F24DBD6829E1C5CFA50BA6BB9CCA3833C418C279DB0605509D6F9ACE2F2AF0AA5ECDEBC506BCE63329F259207528CDF90F5499F69D9D66C0805335CDEAACA2EBC1EB4A90E0BF496B292EC1EE88E9042A24ED26639D055802C1ADAA59A1FFE8C9C01F8167DA2C1AE3EEBA76320008AC11E360926272F7B3E27F28E70D514056F7578144087C22B53C8CDCE243381B1BE8C09183DEEF9B234127FB199000910D1806CBE9D6F462BEEB364B76FE7315BBB491F67B2B1978D4C8CC56A164F3C0289A32DE32F9BC101D0F4EB1947E460343FDB5422D6E3A313A35D0B69571601231CE56C362D1072E02ED94F6EAC2ED2B6E68D05D5707190156C2697F028F666566F9E5077959C4D5D28F10B651DF4349C6E0A32DB4F3F49066DB861C7EFDA04CA1B726F41B60AC0BB00004F402928A56664568108A6F33B0F2EC45F2065E25D0D37F939D4BB229816F764F616F769A93011F13D397154ACD28AB3C1E4DBEB53FFB367282F8A8E8EC0EB0FC5541BA6654D10688D7CF1F0F8A7A7FD5A3B2EC00D1E320FCFA8E24E22E6D77A377784D3F7F1366555794E094CE0988F38A507323F765967BED47C4804EA126CF6EC461B5E2B1B5EF618C07F8A48E93C52136ED5E938073A684312444B1479817D3462ADEB9BF91298B09407C859D2BA103B9A0CED034B6252D660BBF34A717D2B5F87FF0998BA321918DC48361CC0765A4FABD160F919D14E4385C82D1F33D710179DD7BAE4C8364C47B59AB25C59510B524969D82C139740D6BB63D1A5E7B14BC928CFE05CB2B10CA22AEE3CD5BE398C165827BDAD3D83D27C28200F64944AEB94E54F87929720163BCB6C98F1340C451E426DBF78C05C26179D001D10C257F832186E8C44752970ECE2DBE37F54481D6CFFB61AE816802E3DC6D137114FF746B4CA8A9CDBD3EA5956C241E54C46AEDE6411DB8F07EF1A33D5CBFBB17BB13A35CA639F00E061ACFCD8933BC830C9800D174C1243E88768AA4F6501BA7916DC5424F64E5DE2542F37EA44A2F863A84CD9A4B448302F3DFB5CF8C9AFF45EA01E238D93C365893DD9566836D55D3E0012D333123FD18A0B918B4990E0A4E8C7BBB504F9D4103EF2108E5E5C7CB0FD726B4A902FA3347FD2CCA84574C0FDA505A323FF363DC713744681AB37EF466D2C4A22523645E6B9286C40F8116D652C04F06C2A76F392017394BCA7E99985B461F7A531B9B6AB0C3150E535D863E86E7A4B3C10ECACA83DAE5DA015C2FBAD4685F870C7DDBB48ED5756617000DA4F82A8BA9857F3AD312540AF8630D2664FF095137CA3BD8317C4F9F9CB4E8AE101B19F6E9F43B68717932654EE7106DC4A9DDCE765B96DC85D5E65854970FB1EFF5C0EB23175BC01991DDCD40F2C6FB7F5DE5198369C67DB53417F54B2A96481BD4F1799234C301C3D4408D446FCB75EFA24BEFF5476CEB929C9142DA10C4E1B4B7A51CCB0C0A65892EA68EC9AA6A4127611058F53029BF61CC208E3C87606EE5C4D98D026D890FC6940634978B8C8BCE60EA67A8301C1D2BE1A1632776B60F90338E60FDB2A93D2BF1BF3F493953EADBE1C7F6E8898F35EAFACD6011980CBB006B3FE3238D8962CDDC91BF803DCA36B6C8C5896BE6F8D70CD52F362E7B8946543580F5A8E2C06CBE295628BA9BF1B36D5D0095F841743C04403F59650FF162383245760F289D28AFA2149DACD17BF6CC722815A9CE5426CF99F532CEEE2CDB227B1052A12BF244A6A07FE84576F34DC76C92DB09B66E13073E3D96F18632CE9B2B724EF416E293EFA48A98D865F7BE412B2872C5B3BCE204380740452C01EC1628073865DCDBF39FD620FDFA3C57C440EDC3E9D1D6B86B8003105EB89F671B49C1244E22CF24D164A6525FC819555EF3BC679D92030B3702887EE6546EE3ED0C8243BC3BC1114ED10EAEB9511ED601AAE8BC200CD0D593EBE83F4F0F58EA98B96164B11B52BBA8FACE12124F44D490DCF990C249862E8A3DD40CD0E2A9B7AB120FCA572F12237147EE2AA513DCE4B67AE75B3BC45ABADFF30178F8E3BCD972EC976782F2111D41C9760AAEE3E16277735FFA6F8AE3F90B76505DD307A324386E7FA152BB40872459AF31AAB6767B2A453771A250E07F3A7F8B7F677FBFDA7FB4EBC3B368D482939D9E0A8D5EC29228EBD9460C390C78231D65CECBD494C4656D3360DE5223C4F867CADAE24CDB1C8F8EE371F8077F59AEBC2CB1FEF7FF69B1640087ED587183879D9DE58D777E7404B9EE04312BFC2FE020C9F201339C340AFF4247A142E7EAD96EE605E82B34056F6C25DC8092F1936308B4C20C9C5E1C9ADFB0E0B760A5F9F33C3C6E6D80AB0D778A3565FA9221C10A277FC72E929DF009706F57F5C95FB0D2CC06BF602C71E3136F2F78C9F13AD65CF257A07490B016EF5D8FD16C261DD7B8A216726004469B2416F8305B5BC50EB133092C4044C916228B2210CC6F76CC19A2A4B381808E9257BAA851C2F22CA5FAC357A1CA771EFDC6C8194A52A3E6BD0D46CBB15103505E9E7D1ED48A15BA49B58018E8953645D7AB3C32CE9E7E1BA9B0973C21B98ADA16CACAD1DEA5E5A9496BFB8296F39B827C4A9FD200D06AD5B88D968EA0DD5A5AA4417C3F9DE7365DDCDF78B390CAFAC76D2E430D04F75E12A9DEE6361BBD3AA01C1B6F5AB3B21F1ADC278EDB16D8AA22668770FB3CE11268FB455C4766083E4FDB928727EBA53AB83F361A793C245C4175122CCA4505DAD812FDCA4A59A89F0D568498C36731D675FC358118CFCA6B759D6827581CED4C460F452229323F159A8AA089BDD3F079BACB2223D89652B834B17CB35C6E9CC613BA12CED786ECFECDFDB3D7B7B43E43394DDDDEEF9D1F36962D906F797C39829E1594814F7D261569F57EF18BEE88EA6CE6A55728C1209C441927F0C455DF3735A933A4A7A334227B7AE9DF76A7A003233EC5F5CB7405CCDC836B63AD602EFD2B8010CCAF1CE32DB3A2C9EDB39ECC6AA953D1019A7A017AE6C3E0A2C0F60857ECC181F1C215E4085373F397D6CC6DD460478D10C24E3EC1EBE2E66D523D10E7FC208168745447D64135DC38B79EC5743F8C65E1A484198DC2E25D387168C7482FA30CF9903456A300AAF3202A3A400DF54467D8B4404A406C2DFBE259C470848C320B2364B0F1882172DB641EE72EC525AF890F8B3D71C8C3798802785DF5F53088062678FF2BDD846435019E1C25D03865629C9ECC7EDEDA7A725FCF5D4B2CAC8E72F21862647DB17154DB596D9C4A620F48806BECFAACA252642A0E4638E57049786DD1E1C2C972EC784D9C11F4A9604421C66F1BF0B33DEB1DC1CC2FCEFC78492C5A85473EC1EBE2E66D523D10E7FC208168745434DD533CD4BB98E231B38A293BDAD174528AFC6A1221AA43887392C5C3F71FF356A300AAF3202A3A400DF54467D8B440458FC3D9D21EB5E6F4ECEEECC7AE3001F1882172DB641EE72EC525AF890F8B3D71C8C3798802785DF5F53088062678FF192E94F9950A846C3ED933BA3B2DE586C4679F5CEBF7ACAF95F91F1AF96A3DF508942640014C29CBB10DBC3E9646C698B259B49D420724A0198B58C282EEB5C3E749A27F9DDADCD9FFA11756B022079EC74D0F4B30533A0AEFACB8621269F120E061EFF5A0C3CF101A620F6159C6C0FD990ACF69E9BB6886CA89B53ED138E3B55BEECDEC298F4B44FCE1667E638BACE079918963A07718986E9B9914A6BBD09BC74D0F4B30533A0AEFACB8621269F12012F7D8712F52B9AFBE60BB6450EC8565E58C863FFFB6D2D12E07A075739D25DCB32467CE8142713BE6672E87B184F33CB4144E020FA1888262F841162EAAEF2B43579764937CAE17DCE483DA217E771DE0B7FB5FC86DAE66C6F84C7E07E68A45DE3DF701B7105875ADDE96249FA611A80EE750FD99467410A4EE5FE39D2F63C7BF7A3AE2BA0282940EEC048A7D81F9DEC74D0F4B30533A0AEFACB8621269F120525246DC973F774043252AD3CF52393DED94183B8E9D15E82E432F47A5F37C5E8130C86DB98F1150366BDCD7CE1AAA39B4144E020FA1888262F841162EAAEF2B43579764937CAE17DCE483DA217E771DE0B7FB5FC86DAE66C6F84C7E07E68A454AF9AC0B93E7ACF58D2B126275A55D430EE750FD99467410A4EE5FE39D2F63C741BC58552F3DFCB86293F894968D87B0C74D0F4B30533A0AEFACB8621269F120525246DC973F774043252AD3CF52393DED94183B8E9D15E82E432F47A5F37C5E8130C86DB98F1150366BDCD7CE1AAA39B4144E020FA1888262F841162EAAEF2B43579764937CAE17DCE483DA217E771DE0B7FB5FC86DAE66C6F84C7E07E68A458CC128452EB84C107F66F8B4B2F9C2800EE750FD99467410A4EE5FE39D2F63C7D369B09A6A5FE25D142224123E5602FE0273085D89F573D015D49F69C9DC381F09B34BF70A70380C8AA9159A40DDEC150F61E82292C8D7E88C58AB000C7B9E56C0DC4D885F18564DB87B2EE9DA8136391FF0E07819AC249B4A861C162F6ED8EB979926DFE9E2C0F894094E088103F641DA08528F71C2204D0C78233B0509F5992753ADA7FD1E96820C3C514BE1C4E99CF43B1834765CB869FDC46644D2C70D48A69DA4DCAC498D4395E8DD905231C8ECAF78562BDCC96064AC17E2ED262B914CF763A31F00698D23769CEDB9A43F744AB134A56226AC016AEE4F69AB3414D2CBBF4010E90FF7211B2C1AEC547ECFF2837EDEDA7A725FCF5D4B2CAC8E72F21862647DB17154DB596D9C4A620F48806BECFAACA252642A0E4638E57049786DD1E1201878C150CEDDFD34875BA3E892955D55820FBBF010FC7332136E4D269DB90F128D4398ABDD3D275A21AFE067C2C20E21B27A167C5B0764CE0673A69793A1C110062503532F2818EF8BEE4ABF1CF5E9610210AADBDCA6D6EE25683478D5BA77C89A2888FF7E5D1E5D17B950572DDEB41F36DB0278BEDB21FB29D99F5113ADCE71A858DCFCFF218A957B96027914ECCF10DB840A370D66D5301C905F2F6F5160643AC4A12D925D9DBFB7460088BA1968389DA6D169143BD0763BEAB73979C0C2319C9CB8A7340F9C7E24C65CEDBA15B23ED9C38FD9F649522C59A508ACEA371E11C088FC291FF08890648C32199B4AA167BB8F83418592041FFD8F6B6883D6C7B56E795EFBEAD0CBFEE7B60C70BFDBBE79C437697C9D353751364C5322188B2FD7059D0BEB29AA376AD833A9BEF0414D1C99D09B5427E93DD533CA25A931AAED027E94D9B8C9FDB94973EB5F098809BAB8803D5DDC35819D9635646F4A17BE32D724B40706EA41778AC28B1C2B567A3DA7354CB618C0BCDED08E1DEDCF2D49DD2155749630086DCC07888254B6BCA4C701498DBFA676613FC0BE57673876878F3E754FEB7E849160F84682DA29B7A24E5D24967791F6BC8B38BE61B855ED0095839DB31136A9401B6D8899B7B0F0253D2C3B4C4818D1C121C3B7911AD15ECE100DD1459A4D14660220932F5B6BEF9FD24F72A9B2C59B567A63B5A389B4FAB8A959EBAE04752298F612544A65A625A19A838B4FA99429B61D783EFFD9554B25FC3BF24ED8D3CBC357CC0D166906F08DF5500B958536BA496B23B5B7CFDA98E7025DF3212B1FFF842FDEC8E37082DA51E3BA2390D182C363B7705F20575DCE8BE05799F45CE113BFF3EBA5BB46B537838C0FE739C3C77ED252E97AFD0BB238A57A518C44660F16E12916CF0ACFBC51B86EAE3776EEEC83BC1BB7615AFED1925ED77BFA9540BD5BD51F8F34F54D099B1C74653F03F7A9F854AB0DEBF8553839CB59D5D334FAD0EE28AC877D0F7E5A59DA2DA6E328493916C52FC66D14FAAE4FFD09BABF1F6A8417284D947D0C8E80910558569B3576F59417DE611BBBDA0F26913FC6C7F595170F495FEF4593D69AE29E439F7BEA86761617CA1ADC2B7616C69FADBAC7D97E830A83020F6B07D467DB8E819C62530F180C022C087E616EFDF73B380DD5035FF873C69F3D6CE063A371361DCC1CD88E80BD22DF2195E58C5E4898A645DE0913EF32AC535BB2EF04025747F900B54FF246CF62831915CC19228A403E82A485F892DF24683E149D178F64C125850C9B9FB34D740B346A21DCC0C37AB64D288ED9AFC9DA79119017C42D23CFD5BACAA437CF50CDABCA5592B561EF445579327768125D5A8A6F29529AD88AB1401388A5D46F14F76D940AE69F1C9F743290CCB73F0B161A354368C24CFD48B1C471B310CF48E8AE3ECE878CF84C4371551621C2A3B0CE923A90C301B6F30CB7C36FECE520535F83E27EE8D9ED58155EAC22DE132EEB452DBF1BB5FB68AEC43DD55069A54371F960902CA4362DA662095E7C09A25B16881ABD799CFEDDDEB5C1C684E61ADC0437AD806A6B3B4E6E9F86C2847F1A6F4C1ED12AD01EEE00C49FC2F77E34D0561CE49FD3C254D650918F3541E373F0BF2AE07BC2F3EE193AC49749AD641D340EFBBA6F97988190F0EC0DC08FD7A17C0CDF8C1C5ACFCF568F75B53592B7171CEAAC6786F0E2531AF2E633B4B7D22D3AD0F8C320FC9F2DFCFF10A27AA22BD997C6EDB44FFA62823BB94CD03F59DB56A7158788441E7C892C9F019F960D0E7AB0FB6E3CF24DD277C8E8A1B58DB0706E4FB5CFB6C7EE605D1295DE401BF0F16D1724DCF710876E645C599BCB3A87D30625D156156F294009D6C932C0A035D1DF271A933B5B03FF46F6D3FDF2E78CA11CC8138FFEC139A9876743A674208121CBA7883E2333027A8346DC0228D4582C90C49F9F60103DEDD1A527509255E3476BEF0215A10209EA8F638E1093219648073CF5923A10CAEF423847BCD0CE232E7EEFDC21E6D5713649B6088F901FDD9CB5051099FA8E523987483B806F12A92257CEE95904BD92987BB9F634CFF34E7FB1654B9CB0804D4D88F5F78385EE2C8454EA74EAF2049D430ECF6D15BBA04E4E290DC94379005A5F9952259095BD042E76B84CD806343CC01D2DEDB64410F933B34C1F0B6652EBDAF5C27902D95F574E06B27A83D2E9A88AA3FACD1A3F9289A52077CBF61ACEA49D1DB0CBB70618FBBA8F1E783CBEE58EE7B055FA8456FE0D351955535167C34E3B8C9EFD3C63C2AA79970E59277173775C5EB91A101C70076ECEEC4E539F4D39254AA988B3FA27AB10D4075DCAA263583553D7689DF98E366D5B23B2E1C78EBA5EDCA2E3E213FA371B743623A9895C7484EAA1AE84D91F42005BFB62A8E50BA38BBB382A71FC92FB89F08A2C9FB2FDC5D524509D25CA5A93D189D25AFC410BD515D4159783DF3561762A78B8CE862F9A50E1C53E719CC8C53E01041B4EE1D679C20A9488CAF5BCC7C9BD66413D60C6148A199580687DBD9C55ACE5B78881613F26F32C35935B79C036074B93412A1C4A4C57C36A7A14FEF4BA2390D182C363B7705F20575DCE8BE034027B1E25B8346F93197AD0CC50E9E25B32BEE69C3A2C943C19DA82B8B10785D7AC923486F3429C2F2D0DB312FB54A3268E2D3294F116FCEC32CA91BA72B264D3CE8D4787F753B3508954FE655695BFF16D1724DCF710876E645C599BCB3A877F903C41232128523411D5D1379C90C4EAB3E63A7F616C5AC139A58E03832C1366296E63851C32D5B122EEAED63BE4FAC68B17639DB5CAE60D1D7F4ED9C7B8E147D557A9A6DF1281C69DA22E83CE53644FAA16406316B3E1601C9B6BB0F2879A790B7D66CD43E9836177156E3DAADE5FC2827178C479F9AC3433FFF0ACC4BC90D542E9A09E53FC91CD50827C9979F66F0F4EEAC47F341B2CA6932CEDC9B28687ED386876F68938D9E4A099B51FA590F587987D99E053DD1F5D9BCA540C69D866CE2CD2DACFD1E729081867579194B64783BEB0909DD513322CCC610435B4169499C48745A2F15A6FFCA8BED684EE6F316F6B85C29999349FF8A6B22511E2DFF20D5E7BD5D1407688361BB0C87BA33278546C523057CEB78BD007805E3B4EF7DDCF4D1D099B6E639C26E538BB91BFAEAE99518D7785C9458A5C4361EF6C4877DA81F42F00A98B1DAD20DE71610CD0544B702C9C9C62AC34B7481CA047784192F882DDFBAEA6DC3C41F738865E579AA23D0F27352E455475D74173E68980595E7FE5ED277FEE6546B82128F80FD183BF13CFD64DD5958F99ECD37834B60C7F5ABCF081F6AC15C1904894940B2CB8229552FD0D2C80EAE0231A72ECDEAC5FE3AA0D419D66FC1DCFBE5E54F69EB085B8D75F763094CBBEFAA935FDE5CDCB7F52383DF31DF10B000CBC5525AC72C017F7137EE09639E76C63246EE6241A6E845E8F352C646920B9F8B8B802E11951095D00764EB952F669F103C5427AD8177E19E09BA1932EB87CD09C6FCA87350DEE0610ECC9D6AF220D8705FFA18686293E051062306940390C50760767B18B42AEECA807A06E66F0B3FE2CBF3C1B86552AB11D6B5C8410663B541B5FEC8742BD25B6E5E63695772626790AB6D2CA6AEB862B6B9A3E530FC34582735D33DE122E11CAFD6A7F8F295711996E218C7CE487D18F5DB118FEF2B63BA4A73A4441F368266B46232F893D4A761ADB5FF895A8A897B1CBAAD208F1D7F89C3CD05330F8B32EBEE85B17AA71936512777A52873AA66BD82DA648518EC47A8A20E716C271A8D372E69DD04F50CC9F7573211C7CDC468473ED9B19DF7FEF2671D11FC4AC6106E8DCA20025B1D1A90ED311C1954F5EF63ED47CE573A7699771813F84D1FF2B246D5A73E6B129AAEA20DF3EA80FE0AEFD5015B4003E5318EB46F1F3A3103A02F95A07589B73F0DE0A9F19CB90402F4CCDF2566BB809AA50E39C06532377541BF1D06CE1AB14053B5731BD3374660356BD428F77F23AB1D1773D0D254E206220861DE1E61B49235F378401F9F05CB776CE7C5FD477C6E0FFD69D4DEF00AA6EDDB67462EFFE39A043BFABCBC6421836207B9A7E2BF4A583FC9FD8627B3500DB4051BE4232B1E09C08A8CFDCF6C767FAE774CA531FD7A2FC7179A881037096729FA2A078A560AFFE54568B25224078B378FC555A56375B8A6C204BCDEDA5F3FC5B37DE1F51D277C0856FCD800F66B51BCD6ADCDCC335C3181A766FA83307C8D6A5AFB91748C395BF2D0B1A56408099B3B150912B524FFAACA252642A0E4638E57049786DD1E1C9BF1F11C20204E9AE636F0128B22923C6F49BB88FB34155651EA046C7CF5530B33ADA80A14351DA4CD9D17148BCC1545E393CFF648B6F4B84380D0824D3B41245CCFCBE8F7890DBAE4F419E56506DDFB7F3F063E51D316B84CB3A382458C2A9AFCF6458F67F5C7538077DF91A9BB08D85CB4B641E0F2CADD953EA3B2AEDC5FDBD85F3D8925D65F41C7AF698045DE02391233E4A34E1DBF4020037E8B02D753F941C15E70EFB40F910ADD901ABE334B79A0CA3C28DFB3FEE5802EA78DCC5B2309B8332F088805CCCB013B39AEA9CD400533B896DC6E8C9C4DDBEE1C15557FF553E80A7A51B5348001B6E07A36C3818EAA20128EA0C69928A4A17277944EBC2F7AE0A76EB11E6187657115F0295C70A1E5A46DCB16D5903BD04D071AD5B9A7E125A46DCB16D5903BD04D071AD5B9A7E120458C0B3945CF462B298A4AB8A7D4BF09034AFC7921493F6DD0481C00F980286601E478F4E2479204C5F17337567B2AAC9E4C3A7A7BF448D855E354F8EE6443A98E0EBE060E7EE1218786A10EB31E5D302DC0B3D38E79185141251C1C8DF289FF4606C49F808BC063BA23B507A56621E539638627CDC6A397B76F12A70A889AF07909E2C65A4943C9FBC0D55F81A24B7D57ECD956705A7BD044D116FE8DAF36A23E08087C0A96BA03A3E27631AD192B2F8B7DB714C4389284C546850D06E61806BDAB443FE16A886735FAAE55E52F4CAABCB1EF4249DBEF799F1AFD5D1E27F64269C46F43A9015448B40A0ACEF01A0CD060E2A2A970F1C4195ABD8887C6A3996C69D18847B52A52D4313131F9FD45A46A90E9D9AFBDC3F51385141C11DCF0F463D5DC2ED6CF93ACA79906ECC2FD16B21243C6DEB8C7813548ADE1542523DD1ADBD85F3D8925D65F41C7AF698045DE023AC76BE8C479DB11E92327CE95C8ACD13BD85F3D8925D65F41C7AF698045DE0234596838E9EB787D7BB592A0C6D3B9CB2E02483B2E4E9CC5B2A489C5372348880D0502B32493605A5825140310E8F1062AF39349201A1F651B97A05DC163D5B1E3AB5321B9743ABA45BDA10E4E03376BBD6D643EDCB46D17B8084F845FA2D3837EAC101CC3071AE824E3A8EBE5C2083CD3F2995155B43271E489A7CCFF0609DC48AC0962067916437304258E0EB39BE10BD85F3D8925D65F41C7AF698045DE023471FC11F929D5AC57EB4826B3A1D6FFEFA7A88D706E0300A66B5C50C51DF2A9BBA470AB2401512D23E0C74B5B8489DAFF0760854224DC80EF1369D5D401A5797AFCF6458F67F5C7538077DF91A9BB08DE5FD3356933AE604FB81F68008A25111A6BF0B55A1A09747474890A7BA50C037E30D079BA25FC0FFC628D3FA8A3AD251A4112EB0951790B21F54B674BE8DC80EF43A55DF44E39A6C0090B31D37860D3707E22CDEBB0DD2BC96A1CBF5C1C2836A68D30F1175F65D96F95009BE6D9E3A8AA3E85F8E49AFF22E39A6C2C68B41E714A543908282D501EEF96AFFC35A614F6EFD9EE808F0C401B1F9CD4D9ABB107836F2B813D347BD4A19D47030D81C9328209A501F38441FB29D1287B928B0ADE1DC0F031324DE5EBCAADDDA72F93E306D5E9A5A814634C6E78C379647469BBB5D1AF9BB6D30336378B3700E3354CADBB9761021B3ECCEF8E4B435F349E574AA35ABDDFA5B29D67AFBF3EC71FC77F0F98406DED3B7F9F0C48E6C2B6711069516D66B22EEEBBB2D15D7C72D38EBA85CBF1FEB9401D2ACAFD6353A509E3BC7E156232E92A03FD2074E62BDF47F28168797634782F7F916161BA32194AAF7D5D8B524BA7D7B81E34FC3D95957D0B7338E82C824B796CD6DB91CA7C3B0BC3CB03B46565F57346B148C8BC1C3FF82E73A8A0E3BEA81FA0866BE45F65995D3325173761D2C631C1F392E8C0C2375CA3CEE91C7335AAC9BAAF463F25BE80AB2FEC4F7661D7CAAAD14AF3F6DB2C4A53BAFEAFE9F86B3A3A847DFBF4A315052A79132DD5D77EBC6027F586A833226D440F1F2681F102B8991E6251F0D856E31D282DBFCABBD57C33220C9A6D2264AE5AF0452F316AA7EC9FF2A87767201525161948249861B9A5380A699251028668E5767EC92363C20D4D2A4B9B37B0A603B4BC03643EF69A0274B8A20D46310EA441D91533196B699BDB0DB462A3121256871242602C0A460A5EE1FBAC2A654815A9A1FAD37AA5CA15DE6423DC852BC35F4B52A1C50A380E40D5089E7D4B4BE114A7BC76870333FA29F1FBF9C2668BF0C1CD09586A2A39F6341D3488128DD38CD5EEB5D0F975754BEEF7C2BCEB87181F1337D86F7A35F9C8A8960D206FD9CC48BF2A6D4AD386F0FC3BD85F3D8925D65F41C7AF698045DE02380CA9968BEC8C3806BE83F9FEC0AE17E2043BC47185872D09852C85B98FC678BBD85F3D8925D65F41C7AF698045DE023EB4FBE05DB26F2D700F3D49B201941251FAA39C59D6014979B1B79CC70C525059E47FF03DB6ED5D45448EED8C47A9922701CCFB2F3B633B7495E3650998C626541D3488128DD38CD5EEB5D0F975754BEC0F5AEA89C5456E8C8F1A95CEC674E8AA82201B75D451F7C2BC03DAD6A9576B4F2A237635ADB337EE4D4D594B41882BA7A0B11D6B701901978806C304FAFBA64A544C2D5A67E8669D652FEEDC83BF5FCEAFB7305EC214AF84A3393DE6E4A766ABD85F3D8925D65F41C7AF698045DE023466443ADE24BCCF6E56A13E01F712352BD85F3D8925D65F41C7AF698045DE02363EE647AA2F1F371068F64BD02E5AFDEE9A06B1605945808BCAF15C34E9552F8BD85F3D8925D65F41C7AF698045DE023C84E6D724637155406C9A08884420A3C41D3488128DD38CD5EEB5D0F975754BE44CE5A0D0DDD48CF43E64B4F63E2447E7DCD32895D220B01C35FBCA04EEE978FBD85F3D8925D65F41C7AFF \ No newline at end of file +D193A38548D8F92C9F96EDF387782AAE1F1110DB8308D0A5F393E5617413046E0E474BDB9E0711DBD2BFED41AD3AC655F2F53AA59FC8E6FA4EA591CD227B6CD0D71B9B65B10B73A9D0D6E086340447750DA4F2968523C6B02BB55EEFC4FFF5408D87F914981BEE9BD2AEC641055993DE620B2BF0817E2733928DB1EDE5E7CF63435C79AD230B4E1813AF9D7CB2BEC613912F5ADE2C60F9E884C02890B9958C80817D822D9C45B93B4B0832C644D05DD71F96A8A410C597C8FAF996F8913F24F15456466153AF6B13F4E4B81BF05B82981DD8E042E9F3DAFD83F8F306B30C1C1C0F2F01D253C84C61AE55ACC2257911208A112BDB557CFC2DBF59989DFF0D8A68991117D439AE45F1F7ADEE8833A4F945B65611F3AFF39DBACD4B92028D4E1AF4C0617D430E0359294DB1F1B62B76AC9A49281E02B26CF3186748157229813BC741830685BEA080685A43F36331BCDCF684E4226E6F2B08055A0D2EC61F49994748D5D2D4B00842B91A19BE778D79C0A090CB4DAEE4FADE4C04F6C8D9346D8BADDF15ED581079771760B968F91C738A3500965729FC0DF2946C4770AD8BAB260A58100BB9BD1EF8B050A89100E7F7A32C55671405DF8B9DB5EEDA3034A263776E511748D54DDDB9841F6E64E5E6FF27B903A986641147E095DFB97B940C99241F88C4DCB9AD672345F801B53139B63B62F62C7B03B5905F3C3DB6C3BCE5240AE258CF9FF39C6B27F1D7995074C20CBD56EA63DE875CBD4115B82C268829785CE345CF898FD5BFD8DC54FF25FDCFF3FDD9A4DA3F67FB8FC2E9C3EF90D906714378CD99C6888ED392B948A76D000ECB2ACD53D081A2D13C12BD71FEA42DE43A8CF16AF620FE8AF4AC4732052E228D2F534AE167300C73A33A596E57C419F188FF226B84E77E6B76A7068C9B6F73A68E5602B2FDBFCD4DE6755044B9AE2ACFC42A7358F9FD6D62DBB8AB398519018083E7FEBE8D4582ADD05A5D1AC8862606C83ABF9F65FB92D273BE906805A8FBF2ED37E058752AD4548D8129A38962384E1E48D05C28C59970E3C6A2CC8EDDB89C37B29D1B1484E4BC7A7DFAF62C6BCAE2BDFA54D9A486E6998A52E2F375AA68E6405CC81DD23D3D261C9A09E9D5CE8D982FF355F52C6C234DE463A485977F0CEB2E62E91F8AC51025D1339D4DAB430FAA7FC98C9CDD8E8A824580EFB801F7D17C025B824F4C1C74EDBDEE483B974DE6126F0BA5D57CC6C84DD13B9DCC5E826246C82D1B0426A4F5E7B8D0E8BA19C517EDB8AD46D59724947B2C36799A714A5C2A141A6C0DA4AC060E4F9F980E86316217493E25971CF03B475530285CCD48718709D701DB78266D2E6108C21CCFD2F32ED4DD001B6ACBF566403C140176417305556D5B2A4A710124E0118A4ED8C9F9C73CFD75E60FDF9BD79089C00F652F8A7A082000EC7D3D1E30C28CB9AD20F76AFCC2B042C1E24E9C5084FF75098C7461ED0DB0526E9279FE1FA66292309B039F2489E67F124390C1AB4A1FFF4756E70B769543AEA5C52296BFC3625F6896C3B6D1C1D7FEBAB5B630FDEE3421ADCEFA139B85DED5A461AE81ACFC4860ECA8DDCEB6A1EB65D7595F034E2FA5351EE6FB7066288B555584FF4B5260EBCB13302EA7965D2EB631F733F48B3D182B584209705F64793493F2837ABD0B88F096C8367610DD7E6EDF6D16519A4CB9B2FD37763CB38ECCB2C0C7894FFFF0E6A23C4D7EA159B5207F4BA7B37ADE268A17CA94D8F6DD470538BFD91CCB9397804F1F0569EB927277A516BBD0DA42132D0263CD4EF2EE8981E02BAADE5AAE50F006838B4CC54559251BB70E64F69A6D30180AC10ED08F8B26E6BB56C16FC7A59D6C7D14B82FCE923440096B3F12E3D45D8937AAE0694F20F0458D942D7438B5AE3546E2CB3931953F8DAB4E034F01C8A201EE0184AE45C53BC38F49FE1290E359EF7A34E2E5D61743F242B7EF0B104D867EC04A06EB41C1DBD36C5ECE3B90C32426DE619A2D87EA177268DFBD31EB47F189BB43B73CD6F3568AAB971607CE51F4881910EFAA8EBF92850C6DF6880E8832F3109DA2ED05FA2C13516FB4A2AA62AB605909BA1176F94471BB383DEC8AD233FA3CB9F82C97EE9B5B54192E294D1F9FDFDB091C856FDD01FCF2A818FAC7D52B55600739AA6055B6F3EE000DED0758C476584AF677DB62AF5965CBE70C4414AA4EF1424F3C1BBD6D3B2D73B219C7B59015B96017FA7AF924D7933D27DA6B397390FD868A074E23C7A0E5CB5463800B0DDA41D39017FA4A5FF28F6B76CBBFFFBF9D575F4E5BC929B26CADC11ECA05D55674853E0E21D833D5A4FCCB0F5E30BEC17EE79F35E7D90BD1A42864BB18B0397B0CAE69B1FA8F6CB5C2648FA0052C87525E7C88E07A2A3E43DAC2741C9DCB02729017DFCC4CB3C4E67E934026A89F53711EC58B68E5A1237EA07B58277550E2D8300FEEEE977300E1F4FE1EE026AF966317F9D77B76D9927C1492046329D031341D1038C81D2DAF991AF3315C3ECB5C896B6A2618CC4AFCA990D993137ADF85AD5526CEA27DCEF0E9A472D0A5A48C8A4C6741B9A95CFA7762E36F5016315D4B60540C80CA604C652982A05887527F086A7D6E964F5F98533C5234C8216BB12C9F29D50703DA92DB0A95FC5A3A4F70456F5260608132CBC509F5D616C7EC18F86754B626D605915DEF700ADC5A58415CB096EA33239BE3DDCCD4AFE385E8839AAB2277D8D563F1C9BE7470D052B932672C7D9733AC71024F7EA7C198C2AFA7158A206F94A3F5F22EE405C947FBB4467978A5584DF6625E1F611025284FF53CEB89D95CA59F5EDE0D106867D925C4E074F13E7F976BB43EA47C7A82D2AD05FB53FCCA6D3F4535442B6500ADE46821165120A81A056FEA4A391DEA6C076C902C1988BA409BF2527D79622D9E4B265344A54C7C93C9751CD95610C3DDD187763ED3FA4C4C4C18CDA08A6131CF69D4786C09825DFF311E06F76A808401D626C96ED4BAB1992EA405804D89AAEBD00786B32A39FFF6F6658D97DE30E7B5FB56E072FA274DEEFF9FDB6F90FE62FA5606E44750D55340515F0E4CCD985AD1477653AB8989C48FC1124B1F230A7843AAA1C8D7D7E4C71D332600F326044916F1CC40A73F06BAD4909F5B3BF3BC11687643C799402A858719CBDCF511DD52C957E58F89288042565D3EBB6BC2A7DB3D654F84416C5DF679D360E717915F3B4620AE8DC7C29577EC6AE0C04387096050E8B26442BC7EE05F5C1BEB8743A66C61D4105611CC980CFC597F9067AB1EB04917D15AC84B5E2D70F64F0E4AA345C85586535FF84670E1D44CD202F3464BD4266085206648876CF9D979AB0AB4FC95304B5458E496CA73C57A6769B1293FF5E60FDF9BD79089C00F652F8A7A0820042864BB18B0397B0CAE69B1FA8F6CB5C2648FA0052C87525E7C88E07A2A3E43DAC2741C9DCB02729017DFCC4CB3C4E67936D7AA851D75A98689178574036C731EA5D57ED4ADDA3080E758672BF8F2B5E9C9EEDBB2F9B08ACE2C154EDAAF9CAD3FE849DA9F49D3B8F50DADAD7260CE3BA5E60FDF9BD79089C00F652F8A7A08200634733CD567C2ABAB043D9A1729107FB8935A16A033A14C8E04ACF9272B1AE6B37C5741CA612C33DA393783E4019C46B40AEEF9AEC04BAC299C4FC3A4947F26272A1A6CEE1C46D639D60277B049369F722B6F5E2AC4E5393B68B20D94E75D388F4E2984C4DC4CEBF32A18256EBFCF5C2D2E92FD912A8F3C39D08700993BF9E1D2C348CBA1750950E441148EC41C37F93CB012CAB6D01B9FD3B7F6C991CEBB6AAE501041A8AD33FA7CA35232B94F70498CFCB53FA60A6C101767C533D3AAC0536BE1EEAEF63821FF8291A922F5F26C898B4EC36457D57755DBD7405C4ADEB3E8204F231FEAF0292463C894287E70A3BE7793C611388FFECAE622911352C3E9081118BF90EDF23D6C2C359BAA9976F50AD5070086E71CC4CF1788201F6E860DB5C6239C4C1565C6D78322E39B47F343B747D6D9B298EE9AA994B8E2FC7D0EC1645CE5AC55518D77645C46E732980A1FCADF3337E03DF4870370D7DEBE565CAA7DEB6BE97B7BD4571551B4B086C9C45B6E329F4205DF90033998315782F60E597F53DF5AAC2985CB4918C4CBD6C1AB57C50B5573567F87BAAA30BC760868E2DECC9FBEABC41EAC388AD2008F2BA2ACEA54118522A6C218FD653B789E55917205311BE517FC801A96E01B1E67CE7D68A175376C519F411F4A47462A03B303181518A599C4767759A482B188B489653BEDE7C6B990F26EBEFCFE167C33AE939C86B225A98615B1333CE760A7F7E64821F66EDE231623DF0184FCC268F962841CC52B2D0131D3E1FE308C6BADD37F2444FD1E5F7FC4A197C48ECA4B0CE0C7CF65A8879C6E98FC1C9E37F0C07F5082DA7D2C890E799EDB5B183225F2ADF4E380181A01C1DB78266D2E6108C21CCFD2F32ED4DD001B6ACBF566403C140176417305556D5B2A4A710124E0118A4ED8C9F9C73CFD7E3A5E28DE83BDA4F14C81430F79B59149A0A0C83C85091908664F09C116AC7054A3327B8D730A860EE00669E91A3CD70CBFC52FE0C3B992EAC898730FB4AA0A84E133F4283120D04882910CBABA9EF3290551D6E3F753872BE03EB7836AEFB8CEC0DCD45DF51BBA74261EC14CC7D643C1136ABBAF748A67E699A298B1C3F1B9371946E13F86EDE3A87343EC488D9B0500F02011315076DC447038B3040DBA1AE6628A0B4B7CC814A824A1AF2AB772FA6CE15C6F2D26FFF0535EE089F724F9AAECB006E5B24AF6FD86A3F4522FB271E037A07D7F7E121FC28B848B89AE43E5955DBFDAB87BCF2CFF2398A444A21F9CBCE96962D776A37C4217055444A504527647E2DAA9D372F35C2D5E728D286C5D2EF4F182DC7044EEE9955D98EAC48BA40253E197EA19B6892EA8E465EA6B9450D25678A24F4D7A194207BA44F4558CD9C6F81DD23D3D261C9A09E9D5CE8D982FF350C3A785C3EFA8B2DF89E9676FEAD3ABAF5ED22F9CA95974ABE455AF670D371F9708570D605A8EF1D772A46D4A4598DE7A340E3CD1C6181494E4CA2FFED2FDE9085FA7AAD08E9E53712F530223A6EE675970191E16D0257681A605B5FEFDD2377F3CE496718E17E87B97820B63F3B344AF5ED22F9CA95974ABE455AF670D371F9A2D02EE765B7A1A4479788CD01D29C650EED3DC0DD2F5D0BBE37409DA166DE04FECEBFBD086ECA394FEEB9CE7706D086C680FD4585E0B6880AB0D43DB7E4E6A32C6BD8746385F0EB59A306823A2B6238F124390C1AB4A1FFF4756E70B769543A6428CE59AC277202272C9BE75B3BE48770040556E3A898209377EC61C11BB200C93D3D60FA4434E3D331192D4DA0A66DB6E79A697C7AF5EA38BCE079F8943C3B8ECCAE67F78FAC53DB3885440D407B970D02AD51E6F313BCF8B31CB7212C69540D3093DD8A63CCD8C6B905CB24445ECE23E9E41C1FF16C43979FB270C125A7EB2F793B057C27CB8634EE5CAD4AF262A1B8A2542C6FC3F1BD8ABB57185A128C31F5A03E5C0649B0FC00907BB251E1930DC7A0074337884245C90EFE9EEB3DE43FFFF6A6F25C1582093BA39B3EB0015C25C89E6DFB0DCB101FFEC422041F7855281B646FF5AA7FA152B71E9891B9ECE45C4E7D818C639F34FD15C9161FE715A9D680B3433DF504FEFBCFC45B4A48FF7A66B0F8050668D56ECF0E020C98B5134636864D05F9831BFDBA7ACEA3568FFE9D9AFEC8397AE08A666AF7EBE42AB82DF7CEEA4A96E1D6808CF330D0E87A7E325001173A7560DACBA924630C093DF7464496A01C2CC880231759906C3296BBABE5CA609631B87FBBD24534C5FE5C9C8E92DD46B74999C4AC99B8AE9E36BDA3E94C9FF638EF4C11A4FDE3C0B42CD6029B5DEF5C2A0315EA04748D2F31E9E5A08D2757054B90B5BFD0F7FB2489267D070C05C6BD50057E660A48B5549BBF626A61B675C874914C34E4A36642288E13042644087064073CFAC019229F32D7D0146424C15BB62C4A29115B20900BDEA4D62F92CFEB77D6755374B91B0DF2BC67735308F8C362B1B527D184B01AA8B6AE082AF056F4ADB5E9BB3B4EEC31676BE5D0D2458B71CE2AD4C96DC0DCB2DC80954DF29615F5D3B1424A59765480E7C1BC1FC9B5E5FA4EAF3ECEA4AFAD6833E6C23AEEB1FADDF06EAB3A65C21AFE1866F810E0D2F27359947C1ED278670F6760D1866256848EFC42084AA7B08E66474DE9B4AF608D790525C171097EC284EBECBBEF903B973F28128F57F7FA5EAB3FEE39F39F73E70AB8DB7AF6DF76555F2C08DF2DFB0BEF91B7AAEF075D62923156F06A6CC7A412DCAF299CCD09E7A4A73F265FDD820278B29EA55D04FEF3ADBF550634240524BFDBFDAB87BCF2CFF2398A444A21F9CBCE96962D776A37C4217055444A50452764020A51494EDEE4A776B476D9896791E5DD25F0387B4325179A59211977731481B0CFD3B95FEB136482280562CD92EE23E515D557739091007B7DF36F65BC0A814174381C9B70CA4F3719B40BF206BCF36784620B572B0073519EC00D70DF194A1611552E481D8CB8984A9C47CE1D021BB2F393716300687442355012A701D45085586535FF84670E1D44CD202F3464BD0A8D509DD2E810D74E1B9345B354B05C80080BCCCD51912C805438511671665C42864BB18B0397B0CAE69B1FA8F6CB5CA4836D147E5126D5965FEC07515F182FF379671AE23451BF61CFEEA21B6392BD01C49FDBD8D14C9E72242920DD048A65A72F2509A1E0F41AF23375B8DF35CE0C26C79627CFD589744DDD73A245A9C58285586535FF84670E1D44CD202F3464BD8A9D29DCD61AAEA6D78D18BCB9F05DDE977D3D797CF70326472577F7EB3020C169617B352639D23CB5C282376B4C6596A861BCA09DDE17E70C65F1284CA8E31C50EECA7862BF57DE5BB290F5266ADAF6403F1674010C7BCCA7F777E9BDE20B2CB5BB3E933D1A1AC3F70DDF972F74ACCB0B04E696DC5600C17633770D5E71D13647FF067A9E03DDFFBC5868F5579C0A4AE07D75831050E7C8D135178BE956E0B99AF8E855305BF4F336A6A49A2E06950BA2678BBADB09C1BF8440BEF4AB3D1D9108E835360E1B82850E73495FA25D2125EC4AD08CCE216021C2BA4B29587111D8649C8FDE586840F41DEA617BA590E8B6B0426A4F5E7B8D0E8BA19C517EDB8AD46D59724947B2C36799A714A5C2A141A644029EB7781821F523BB59D7D41DEFF880C8F3838E91A0DC50A3168C176F1970678A24F4D7A194207BA44F4558CD9C6F81DD23D3D261C9A09E9D5CE8D982FF356D3813B751632A4B4956CAF7375AE5DF8328A0601622AA04EC100A2F09DBFB8D9BECBF9BD01EC0120DA0F7E37F0CCFBD751C139FF5259912824D8A282BE31DE0CF018B0CDDE558235C20DBCADEDA2438F124390C1AB4A1FFF4756E70B769543A2316DF5737BF2370F256BA6EDD59FC2484BE22468CB6F54C73E31EF2AEAD37B7EBC269B87C4B29DDFE15A8021B40CA6CFD8696FE14D53C65C9EFE55A92C60790BBAD8AC51822652E1050D3854196218E4909E1392DE7F4D9972BD1DCD6F33077A8028065D19B24D5FBE981C7E87DDC2EC53EB66AC6DF2B95A8CE4849F2D0CB339A09E9763A5BAAF434B5B4E8EC7CB4315E60FDF9BD79089C00F652F8A7A082006988D54D60DC5755E18A175C2848A25480FE2B0C6C50A151B4F8991A3A367FBB018B1C2FE08D0C4BF5F8951D959222A4E3CEFBA19ADBF7645FCA7E4ED70B142C5E60FDF9BD79089C00F652F8A7A082006ADC768EA156F676D11E5189993223D5F124390C1AB4A1FFF4756E70B769543AA516F1279B3C6749A2DDBE8F4922041DECF6BCFF3D3DA17D486BC282BCAB7EF666321F0797E36FB66608941333FDDC8CB8A2542C6FC3F1BD8ABB57185A128C31DF19D34700013DECFF16F142C375AF7BC95CB9F7F4E9701594A423A9D38621398BF9D02B01BA3375E690FEB09F72413350C7CA82A4C0E5AED13385BEC1ADBDCD351D88503C3EBB1F9653D1759A3D11B4B208F5FF806C0EBAE6CE5335EF4214EBB949A1D3D5BC93A366610C9A4FAFC5E955FEC35C0B559DBF099FD661D71023D159E3DA82EF132F37836D32282327188DEE5BD186D267A239C8EE787362B342F3B413B48614460C638522E10816FCE998C1BE220DC9913E2FA0D2F110579281867474092436222E5E462F8FEBF66EA6DB75FCC314772016976ED2CA93C89ED8426EA41B1880EE6D52E228A043D06CBE8BF5E736A0908A70C0EC5307BAF29F1AFC55D416DE91C587AF637A765110C1E81216F67F798FB10A3F18541BD7662016AD9EC15949CCE011BEA096A0B07F43DEAC4ED8C144435E4A728DC9487ECDF7E3572FA940DFB2764CA21CA92F52CABEAF51705CD043BE6E3F66115174800941FADBD5248AE47B066019799DFD59BE2B4ADF7894C456E1BA72A1136B1244031902367D4AA0F64EAD1D09FDAD07D171695E134B0738B6E266F5E5DB3F32B6BD3B4D59070283FC81847B9685A7B54F84CD7D4F7EF034B5A85422779EDE6FFAD03267510C24EC34FE5E1A507B337A59D9AF0B24B6FDEB0D74B8938CFA433512E2212C8C376A7438A4756FCC5BE7FC4F984698CC5CD53BAC4FBB626005FC86D7B9753427C0DA4AC060E4F9F980E86316217493E2DA4BFD967F36546735F1BECEB7C32DF6BC5E5935111C7964F18BC66FDB3CFA077C3A5E028A6B4788087A65DCEB44D778AFD02F12B58A4433D96D275E174847A00DFF8EE2C91097D80E5C230140AC819F95204AA40B905808D19C9669C10B474DC3AB8FEB00A39C43B7781C898FBF2CDA5E60FDF9BD79089C00F652F8A7A082003B9F566B437FF05B8DD7BE10F4A3FD0EA9F1EC748B198A27AAFC300122315024394AFB6452C53741AC6DC335BB8C135601653A47ED22B71781A9EB0F29C39D12094DEC1C39AFBE67BF2A30A8F70912BB81DD23D3D261C9A09E9D5CE8D982FF35212AA754B0C1F6480265181CAC6753306D99C8E1DBA5BFDFA7D7E07C2E27A3506FA66667982377484BE74248CCE7BBFE5E60FDF9BD79089C00F652F8A7A08200CDB769BFE04398F4F5EC2670FAE5E7EA81DD23D3D261C9A09E9D5CE8D982FF358FA6954D2DCD680DEFA8BF92E9695D6B007138E9DA8EC5BA7E04F19A78D4DB8AC65E6CFBFBCD7679CB1B6BE361783DC6B59BB79970E8283220BEE52C7B85E71B40AEEF9AEC04BAC299C4FC3A4947F262B61C0828B301FFE9B2F151147DF6BD8D813BDA2540B0A72E8603D8CE46E5AD7EEE7989AC1FBFE07E5E534FDB421114814D6DCE8F0DC3DEE1BAA31C9E0C8FBA2D18C2ADE2A29987079051993012EE803F44BCE9036813249B47E406BDFF2534AA5E288F54FBC3B8DF5A0E147D24647300B69492BE8B1E202D491C309F0415683F38E7431BA0F0B85379B778C9E97D596C5866136A2E066358777397E0D2087FD1CC761F250D711F03BC998DB710E5A8AA2AA85DBC5720156A7E5DFD17B40CC776CDFC0F94A0B2EE8980FDFE9DBEA499E5DA4A82EF17718D3BD5167BB6FF923ADCCD69F1BBA51FF77209740546F05A25347182D5A778B203B2A834D686E7B6477CB6601938C3CDE68953EF2293034A27AA5360BCB2624F13F17227AC556C43BC6066FE78B5476FB0EB9AD211E68534592B36D00D4E21DC101E6EDC0F048CCAB870101A6781AEA94FBC1679E537FA0C0B81202F4C589D4596B217FFFF262113716AF32033F10485FDC7F8712120DAAF5954DA7E8447EDC01C6B65A9000B69FFA035EAC85B48690A0E1B8ECED1776D8504941FC7BEAA88D846221AA2572489932BDB20CFE381C28FF609594C2235143F2EEA0E70B0DC77FEE7B4EF73A3E03312F86CFAB94331FE3B4C9316DC71FE4771CF46D33929E04D1098E9171565354ECDD59D21670ECAF6204AFAC53FDE5C1131A6364E873614FB73443911E10CD10B3B137F66CE08DB61B587A6AEA950AEB6D0E0DBED20ECD63DBD67A59F149DB463FE0C346C02CBCC344545C288388E730BDDD99AF481C560DA10BBF45F73831873EB54FE4CE80E6A3D128AF7484704F4259DD19C1E18E287649A5C534FFCC6FAA2BC28016B578296D4DF43939E256B0F403E5CE32683F4FC1C7B8A183C10A48DC716EE010ABCCA084C17D2A0B6FB92B9BF1BCFEE05F42B178D683892D25E0C5F7B9D7B33CF0990F1AEF6E1A8B6A88E5EE3D60C640A702580A2CB0CF2E58407E75EFC60F3A04ACF5A3F0F2CEC9C861D2C655F574FD8FCDD884D3BA8D9B5CEC2B415F9E662C34AD197E340E4E09AB39D0408DD8E74AF47C863F4A60049BC4D340F73299EAED075AC504C8D427437D85AC65AF66130D6437F50ED71105F6B9FE83F4B9E8F79DE35E98E1CDABC51D1B4CF82EA868595ECE41A4057F97FEEC4CD7CCBAD687774F37656BA0F329BAF085604D3A57485D92AA85DBC5720156A7E5DFD17B40CC776CDFC0F94A0B2EE8980FDFE9DBEA499E5DA4A82EF17718D3BD5167BB6FF923ADCCD69F1BBA51FF77209740546F05A25347182D5A778B203B2A834D686E7B6477CB6601938C3CDE68953EF2293034A27AAE8A250ECAEE0FF7720241CB3F0EB517DC41A67E3DFD7642A5582249D5F64C0691B4E641AD3B63942780CE3A7632DC2A33D1063B5D9B3EDCC84D19647BE6865CFD4C09F6A695161FBD411EE77FA76DCB14F2F13A329BD0B610401667B6C8F373467FFF6C10089FD8B12104B87C0C82964B80DB71640A03159743F0FAFC547143EB83D0F760B5206366C469386A8898D780CE8F5B86EEE86E9CCC2E02CE71ED83A4DAED88BFBD660CEFD7B798D45DCB9D8CE42B8475FFFCFB6000F3741B0D2AC6FC5EF1A57BB14E0776A75E38D28F7266754E54CF54CA0EA46F18883C94F2317531DB78266D2E6108C21CCFD2F32ED4DD0B6DC986C7E93F40E3DB4551AB007565100F12F71798680E28589EB37BB188303D3E0647E68100211B446328BC7985D2170F65D6D19BB7B9411FF44380344ACE580C285B3493533C162023A9BDE601720633FE17B71CBADC7C67443F7C83B9CA9298DDB22144B084CDD036C0E76A01A8F56FD693FF7B7CFA86C91088582C2755A02426F3D58192EC537DAEC22FE288AA7A097A96B0AE7A6A7C1FF384438C0110D3B838DBADBDACB3188DE93566A0B078DF3B743AC972822AC35F8CEC940BD10BCA93D4FCB23A12FEEBFA2C681BA837FC6FDCE92B2638579E533EB5F73561ACC3662112FAEF62EF715008958144E59A7C530FA3A1CB4B173B47BAACBD8C4156D408E65A298095CCB277AD6AC1F16783C4F50BDF2E189F2496AC18EC81AD1BB3FD86F8C1DF4E7C62FEDC2A48CCB0DC7B3AEBB9ACAC2FC1BBD929F9E68F2BDE666DBCE14ABA6BB56E348F18015F9B1202CDF22BE0812BA474D00829FC1F402E52B128C84BE00165F4969120E84F843764062986049D05463B28507DA78F542893C2E82E326695F5AAF6EC00A274AD2C9B7E38BF9D02B01BA3375E690FEB09F72413350C7CA82A4C0E5AED13385BEC1ADBDCDEDECFEBD83C084CFE757B08ECEFE8396C576FEB54EC70BC14B02FBD3630E4C2B46486FD23E2CD97660082C078974891FAF47C863F4A60049BC4D340F73299EAED075AC504C8D427437D85AC65AF66130D4C09F6A695161FBD411EE77FA76DCB14D6AE1E74D0794A0D79FE755F030F94FB6A2A5FE9C608BBD5CE5143B75C02A50C4695A4D07F8D181246C63682B71883B777AD36AB1614A093B4FC9DDAB0C014DD9C4BD8231D3DF5496E30A6DBAC58092A5402FE6A5C84F8D8BFC0B199068E11773A26304168A1D8A6FFB6C7CACD6C4449861D11F6E4579F4BC4C8278F9161E4B78369447B5821765A24DA6A511D8B1543C17C3174588E1E2B2C97D7A15EF6626B82415828F646D119527D975018F013E58552ACBF408B6E99E240F5D421F53F782CBF8C82DFBB9351572CF2007C8E9A5FB0941570E1A0EF038FBF31D024DA176DD00CEEB6658A33335AD615C06107754304117AE21E05EAF9DE48C458F92FEDB48B1A9D291BE70D99A9B21B00AEC2396026881F83D58AFBCB775B0DB0CE32F885D18237BF3392F65838123E8EBA0B8CFC25381C5D4F99D5787E60C62125D71B463709362C65B87BA8905153CB331787D76A6DE7B2E8CF29C0AE8B9FB6F0B1459742FFA76624348B9AB81EC40AD35D89EA0FEE48A071786325592C66122BA1121813BEFF20267609FF3CE16D6513F70E3EE5B95CB9ABE57F26E7883F348CE10BC67223B71687F2D33077D5BC8CD70BE378783DA098F445DDD0321CCF51FCC075E2F2E9A243EA04DA2D3DE44B27545E22FF372DEF10CF1A16877290FA6310FD88BB63636CDE3DFABE4EDCE4CF427DE6A67BBABED9D8E2BF531D264B65610B12BEE6893845881B1A45A98727B8CA448497E602BE8B0BBECEEC170921171DCD99E48A3D0DCAB45CB551188A65E1BCA844D7BFAB1E675BA01222CE85902DAF8D1175FA04ACF5A3F0F2CEC9C861D2C655F574F2AF9219CD0ABF76FD469296F02281E351D8C6076B6027A6D6974E674B3D2D62374BC8544F02BD61A724216D48CEBA378448DFA150281ADC0FD0DBB2C63C0410376A85C9F75A0E85B8CB4A3228B45F77DB9D123C5C52C44E7019119E8BDA684392E706160A1D63FEA60F0E5F02E047B03E352E99B59E8F2C336B1106E3EDCE1DA5D616C7EC18F86754B626D605915DEF7500965729FC0DF2946C4770AD8BAB260A58100BB9BD1EF8B050A89100E7F7A323AB780946F1DFEC7B2FBBD947589EBB56254F38E2A2710B3C1EC3291FEEAEB59E939EFCDAAEA02F5A145CA46DD41E5CE85FCAB762A6F3A6892450B38DFF5F30E0538F1E3A5C117C930DEF91AC2C8902DE6E1B4D730EDC273E1CAE690009E0B5326D4B0EE0C52D9078BFCF78520BF575C81DD23D3D261C9A09E9D5CE8D982FF35F63AE92926BE3C45B9CA5CC2DE8AA3A37679CB0029B892023A8E42E311ACBAC93C00EF308030F96A5E997B2E39574501927200D120D4536BBC979BA03157B0C9CF0990F1AEF6E1A8B6A88E5EE3D60C642C348CBA1750950E441148EC41C37F93114DB5B299AAAF3F7458B8AFCE2E4EB90E70B0DC77FEE7B4EF73A3E03312F86C2D5BF1D722DF17E9B9BBC102C631117DDBBFE4B3AFAAEA680324691221FCCA02FAB94331FE3B4C9316DC71FE4771CF46815088963EB2AAF4765AB1A114FA5E226EC14E00171258D01C1B704CDEB646DA58375B4147F095214948E0D548828C765E60FDF9BD79089C00F652F8A7A0820002AA9A2DFA66C69106593E1D284F365D736CB1CF5BC6B67ABBA027F3B0CDF445BC7E0093A440655014C985B30D3AC69A4E1526404858C1A0737CC865A4CB4ACE0CB9AE351F7F92B4C228BBC65470FF24C0C393EB8E79484F8F71190DDA71F1045CA1C2C5BDBB5516F7D2D43B400AD92274BC8544F02BD61A724216D48CEBA378A83439CDB2ED39BE750EE48AC55B22555132B4ED790ECA41F2A58BA26493060966F4F148DF74473B43481B948F13208B89C6BDF2A32C74FCC48B448EC7CF83AB91324BB16EEC2F7700455F010100D243C041509468786DD0599BE3F2285E3C2954E54CF54CA0EA46F18883C94F231753ACA54C091B6B412E006651608C16AACF1202DB75B7C88F7DB2737FC4E16B076433426B12373E1AEF4C3033F10680E44DDC3548054E537D40D7AA20DB0BA9C182C7632B3F85A3367E093106C987C1072BF6E166C9D4634983F2A0F6A100F227D8B7F9A7F13E0CFE11FCC8324FA781791CB6E496C8FF5DDF1E8EC95B95569AE9B46F74FABFA2943C5FB197FA58A8B5F0FEEE6CBF015C6ECC5EF85A6DA3294674D1C73323E669BEFD72AA28F36758FF587824EC4537B294F585FA601B4E2D0AEFD267270AA0899517D5552337100B98F6D3EC4A839252B6CC4F099B2EBC6CB52F4133588E0472ACE53FBF83080151E11B954A574EC9B5839310851C3E1E698D6506BEDFADF030298C14FF1CFD97FE57E3F418E5C2E60FB2CE36BC93945C71EDD76B5C41D44093FDD03A3D870A98975872568BCF686D2F73C15590836806109FAF277C3A5E028A6B4788087A65DCEB44D778485C236128BF62334E57365D9074F9AAC16F8DDE83A9DEAC108D9402DB6418C119646A1F77BC87696A406D5904E1733D48381CF0B9BCB058F77884A98BE9292B5AD5F29BE845F7940D28036BC87D3AD1A16148E17977A07A81D78C705F7FBE008EF99BDB795F61BA33DC8BBCBE33EB8154CBFB4908FF071B78C82BE8EE0D599905696A4CC9672B07BFA0DB800A08C204A059D5C7FF972B0DFCC79431C424DE75AEF43C78B5F62B1D23B3C8AAA65021C24266085206648876CF9D979AB0AB4FC97D79EC1B4D102638932383E7E33A1B6677AA7A622C17AA6CB2A0957A299EB0359F65026B66F5C75FA0661F5D722249155B3221E72A4F28B81657D14976BC364B9E7F68817B241C44C6224C79F48AA0C94F91726C621F9FB992AC6E141417FDA65E881D09CEE9CAAFE847FA8C6088B8C84BEA70E221FF155A1EEE1C4FABD7B72CE3C237D551003313507BFF87AF1B8C2B53CC016475C8EBF7CC577AB7C5D534AE9FA817848E34FBFF7BCF8721079C45B3684B4B3E7425471D40A6DB939A0FEAFD6E34FA0B5DFF4BC85F5158D2C4231698E7A718DC92120282102A4F7AE2F0EFAFF04A4887296AE40C1EBE573845E80C178BCB9BCE4EAA3D7F83C37B07F2A2AE8CE2BA4651B2E354BC910E6B691572D345A615064E990E94DD3E3EF77C2D6C705AC37D22DC22F93A5722FD2E2B68D5D7302327993F03713133828494E5BD5213FD240A10C188EFBB5148F2191F4D2821F57E8FEE768B9D6C85099F670F3469D458B867C0F687C248940D62838ED67816F354E3FA230C573003C20896F9962DE6DA771EEA875C1390AD2B267FB3BCDCEC4B3B2FF3660FCDD8CF864FAE2DAC777B41D5FDCAF76B0B976B349A0EA2414425DA670E9C90A88BB2EB2A8DAB17C5210FEC080B63933CE1FAE14619A001F07FBC6C4266085206648876CF9D979AB0AB4FC97BAEDA401D8483C23090724F44375FF2E9B68C519C871848860646D24051382A1E02BE10F9A43436B7C3E61FE731A5C95399DDAB701BCC9AB4B3D8780C5D4F9526D4B0EE0C52D9078BFCF78520BF575C81DD23D3D261C9A09E9D5CE8D982FF35F63AE92926BE3C45B9CA5CC2DE8AA3A37679CB0029B892023A8E42E311ACBAC93C00EF308030F96A5E997B2E39574501927200D120D4536BBC979BA03157B0C9CF0990F1AEF6E1A8B6A88E5EE3D60C642C348CBA1750950E441148EC41C37F93114DB5B299AAAF3F7458B8AFCE2E4EB90E70B0DC77FEE7B4EF73A3E03312F86C2D5BF1D722DF17E9B9BBC102C631117D936E52A7F8E05239FEC06204B23E57EC5E60FDF9BD79089C00F652F8A7A082008D263FD0905D117CF337B0F3F0C07D88106A84728A154272EDF05A8723705F88E597FA500C500DF8D62FC8C640A4C9CDADFD7B078EB07B639EF0D7C2EBC90DAF3D382BE0A5255E567DCC7D1480CF982D50EECA7862BF57DE5BB290F5266ADAF6C8A9912D2992B0753FAC12A9093807876356ECA2514CF8DBEF20DB9B4D90659039C4D8A207DF3B4C94346973B08B39D0EF4B8C2048E203E8EF3D2E621CC2061127F160BB30A57CA295A7B90073AB1BE47D36089A5918A5350B1697F8582FD985D5F4D5D307980DF1F185EB582BD53B7C64644992D2369E1A7BC078145538991BF77029DADE05C7E2C0530AF850EBB0D6ED012693A344D3913E69C65C6774CEC6CCFF414E2968931B58D26E224E83C1C40D9104751CFC9BCE42EECE5BB6599B5A70F89AE40E3FDA57E3C75F7DD337DD7D73431539360D4BBF8704E8DF04A7D8CFE1AED0B2B3343BDD239478089B36B7A59166675C81C6D8A68460A021D5CECDCA03723DDFDBD95974DDDCDEC54D85AE6338523D57F738842208C5AAA68D31639825AA96342A80730D7C2E34137E508952880FE5211D37B88E856585338D3BA273136DD9BDD1422B3CD30034C82A884CFDF49232A2C7EF59B770FE1382DA5D5B5E05E5123CF751F6F0B392DE0BB7023706E28E4E15743EA7E43E76B6B5D667D1BA767E5D7A8C2F6E436E5BC27155EFA59689DE0014723D2282A3A10759748C202B25F7E2241CC663787B934242CC3C28E2B82DE8FB1C82F951964F3304EA095E2EF52FB4CC333D5BA9F88FE97C58751029923B73104AD8B4B02AA55DB1FE4C5380D76DB4DBE91E4750D9AFE4673F0FCA59971F7CE476CF09A95D0C4D322BAD412A2C5DF54B6B0D71B9B65B10B73A9D0D6E0863404477C22E660017A1DF0DB6CA7E046D054C75D02D113925412FA434A12F35BBBE5712D43F70F6B23C727E038DFF7A47552A82A31BB649113A8E66155662EB8B16F261D10658420BE4CFFED4776CFF97A0A448271130E8C69D9BC4F9E8DC1B2402E117F44BDF8F1C667AC460AB6C16F26E306909D0D7CE08846740C043624F54334630A9D52331F1A536A062C842922145D4BC2A92EB8BD8004CC1697FE9F3E35E8FCD29D0AF0684BE5F48B26AB39F8DB0469162531C670B1D8B5CEE36DBE6E28087142D83368EBC243AF99F3EE2FDE2618EF4F8B7FCBF77370DA895FA5FA8C53B99BC02CDC471B5AE7D16AE6CD18012DEE0A92814D1EC03D582759980D7C093D5FC45509CC76CD6D7829F7880BF31D09D6427C967556E56AC0535F29DC21A5FB0257B5A65FFCB36635B73C2B377AF4A4D3CDCF27215BA09258DF21B9EB0812AAE7646D0FE892594629A4E0F704B28044A94A423021A67CFA0F4714F77C524CC872DE3AC927FCA79D4DC8FF12FD8BFF70D42EFD6F471B73116ABC48F40D87D7DA0143CBE8256A281DEBBA09C0C8C4A5E546DFC13CD796E71290FE3116E7FA6B0643B5B51D799E00829BA5D95C9598E9DF66525D9FD5A64CA63FC6B792E11F252E3F74FD63CF26E8E7D666887FCEB183F92C04356FA4EA6142BA2633CB1C5B6C5418C39F8338B3F17C41D66B13133B63AD907FB98FB72A789D7C81237AB8C450832E7FA16FAFDC9678D6A2868DB17E8FB930EC6DD1A07080F2A235C72FC03BA9ACCD885832904E755684605B2F5C96A3DAC48C8E42E74F5E6DDBCB0F6029FD6488D777DD3CCF16DF3AA3A1CDF3FE1B3DBF441FBD146096DB74A2D72E4FC855C46C0FEF75A461AE81ACFC4860ECA8DDCEB6A1EB64A7B548BC3F1A193B0E0AC29D3CBBBF18035BED3CC476BB5D8809888F8ED011B82E8C304F526C0CF1A6E78151D2A211275AA0F07FDB04E3E6E04530416D447FF34187DA0BD2937AC050179E66DE42054BFB45B73C7A709E25D571096B1E35992551A4B179C3554A8D1F074468E060FA74CE97C8F02AB0690BDC131438354EEEAD54A76EA875A3460F8C8B1D4DE37A77DD95B4EC79D3345A2A7B3A34D7ADBC5F994664AFE3D28ADF5520C61940692E2FFC766D986C3199B638235425EB952EE2BFB530B7E4E3216F2552389A91BD39028FB40A9F72598A38AD70EB0B74429EB527D8C81D4AC6C7793C0516D79C6A90BF575032724F77C94222C3B18311491BEE7C497A2B23522C2C1C4A6135083B535964791FA6A45C83F53863CBB7D981B449D0386C7C9FCD25A24DC22333434F888579A72C3659CE2744CFB7F0B12D00A4F09C766D986C3199B638235425EB952EE2BFB530B7E4E3216F2552389A91BD39028FB40A9F72598A38AD70EB0B74429EB52E3CC207AD79CA08BD37F90D65EDF043B7064073CFAC019229F32D7D0146424C17AC09CB5FC3573E6449619BE516008C8716B9FA49227B74A5033EF12005B762508DC31678149791DC5941A192E65BC7F2102F1199E81855B42CF40E2BE18BC9A7D7A2AC5CF4EC44D812411DFFD54126DD2651333D2F20740CBE7B27D081D0531A63C6E8E889A6D76871860AE5A5F5B6661A076B70FCA3B2BDB161BA2A620A2FA85586535FF84670E1D44CD202F3464BD941AD7A126EC4ADE32C183FF69C8A875960D86DFC174C9995894285A81F74F58A29828AA6F86DE4F979227499E8DBE0F65284815A21B1DF887DEB8A08CD8C83F4236B1565ECB20FCA1CA43BA5186FB0BBF503FAE034EA48B99CD3C84E7ADD7485D6BFF44F8F43FC6D44DAC3F7128157688DB263941D98358633FC409F0B4790FD825C65855F3AA4DB8638E8E94461090024032E39EC9D2545D5F674DC4DCAD492919EC0DF4C27B8787915F23B8A46DA0438008060E89454DDF616B96F5BE93933997B7A83454C46400B730229F81FAAFADCC83E784FC891BBA2AA1EFC9ECCB2575B6EF078502B0E9C47DEDBE6713370AB2478DEDB9B093EA3B4565296F835935AF6D4B96C833372195F47E5BB062CC35AED154BC722519815E7F2C9731646750BC183E2C0821191C0D251A9B885E18A949805102E977CF21FF9E5F29BD230D15DB2BA6FD7635EF748C0783678BA57431DD57245B14C503FBEF9CC63027B70948212844643D9653AE84A8436F5B6DBAA61DB59E6F2412345F6C1167EBECCA66CBD77F98C14E6BA24C9053090BEFECEC0356EF575F3F297085369779C621EB5152C37898516280DC2888DE16B3D346461FA14BF615EAB90A5A48D5244F71A534CC2D2D29D54A12F562CE1FC82B31764792A518BB73BF49D97D33A5992D4E03586E1CFFDAFC87B68B2D42BDE6D96ECEFCA0631F733F48B3D182B584209705F647938E6967F5AF954A758DD27343C2CDCDBF73B4661CD8F8FFA8BF5E1B9390F40EFD5A81423E42338C590635DD8374F3F42F54971E5D18CDB2688E482B4F15EAFAA8F5B923A1D15362320C442332FD2A095842E57AAD4C11C5D878369F780667341850DACA74BF09D829953ED62690885D695EEC6A3A79BA5B1136812DAEC950E5271AE0049A168FAA9925107AF223FD90E0596902EC86671162050A53BF68FE657469654437E1C58962ACA7EEAE220D1DB14266085206648876CF9D979AB0AB4FC962D98F56BFC3DE64F58C257B905FBBC7BE24791AFEEF8BDBD87B9F09E374DC49B804DDBB893880643C565599C9462781AA3D214892AFE766EB1F65EE8A052B5830FA3A1CB4B173B47BAACBD8C4156D402152ACB360E685B1909C02FEFE8F69965E60FDF9BD79089C00F652F8A7A08200916936174C238C71AE01403EFDAE5F12B9A334409BB5C17D65516F31D67C0E4A5E60FDF9BD79089C00F652F8A7A08200347A1D545154A734A09C61BCFE5BD9E543D4BB7D4DD64D2C0FB55FE78DE5A0DBF63FD0F20EF70DC79CF52901AA00173F01A38291D41299BBD19877D5582EEC7D5E60FDF9BD79089C00F652F8A7A08200B027986D13E77C6FA4A84EF67A4A1EF17856B48714199327A7CCA8A78D728FC7FE7CDC630FDC4FA4C1CAA1132270BE8E8C83AFDC34C8F8CA76722C49C102C4B36D0A58DDA26C3C807F18E8DF5744DA715E60FDF9BD79089C00F652F8A7A0820066F486EFE4F8BD13894E2F39E94233B999A89890646765CCE732503A403F83E8706D61F4560D7052C1E69832E5D7182DE1A39831A0BB08608BC47AAC8EC4DC625E60FDF9BD79089C00F652F8A7A08200D62E42233A1442D5770E83AB1253F1A8854E4D59673CEA69FD7CE1DDE6182BC87D304E10E2C06782C6938E2913A545E75E60FDF9BD79089C00F652F8A7A08200944DBA2EBBF50A3D1ED49E95D266A767AB95028396E9CC8E167D17CAC462DD313EDC6F3ACFC1D0C1FEA3F1D2D18AB8B7FD8696FE14D53C65C9EFE55A92C607903916BAF47DD8F733F1EA95F5FE850F4ECB1B9700B3300FCEE2491B90DCCF2168584B79232C90C181A3A66EBF53F467FBFB6578DEAA3D0576724D5D44FDEC180B5E60FDF9BD79089C00F652F8A7A08200AF4A463E84E48411449918C67B7BA9F3E98D4959826CB5FBF27B17FC8F298C3883295FC3F3F4AADB14BE7AAA86460852F124390C1AB4A1FFF4756E70B769543A2AF6E613B486A80A7BDAFCEDA44CDDB725341EC3BCB55968BD3D491220E588F25E60FDF9BD79089C00F652F8A7A082003AE56C0EFD5FB6521566107342CF303B9AD210B129B078CB67D72E7FEF11DEFEFE849DA9F49D3B8F50DADAD7260CE3BA5E60FDF9BD79089C00F652F8A7A082004F91726C621F9FB992AC6E141417FDA6A2D02EE765B7A1A4479788CD01D29C65A40C80537867337D0594A5DDE86777965E60FDF9BD79089C00F652F8A7A08200B70BC25FFA1E3614A6898B5CC1D413CB89753D750BFE6796FF2645E2751190CAD0E476671AD8C487168FE08E6963FE600C05CD9A6E89077BD3529EAC8211A138232CBDB7621D775B518F25A113FF7B59111C85701AB0CA46B62D9876D5B55DEA196F58E0992E8C3BA67FCB0C19FAB0FCC8EBF32D81F86167D255044228A61AB8FD8696FE14D53C65C9EFE55A92C6079085EA4B528C834F9353EB219213C32989C5910D566E6A32EFC7696E5DAF9D36745E60FDF9BD79089C00F652F8A7A0820038864BB66DB4C5C71CDB8C698B09298F319EC514CF153CC20892EFCFA9802F96E3A5E28DE83BDA4F14C81430F79B59145E60FDF9BD79089C00F652F8A7A082002C577FF3EC72E117DDF6DE38864287125AD5F29BE845F7940D28036BC87D3AD100B568C4FFD55BBC2D3A232656EC1FF4AEE1E224B268F9CA34E8BFA6D1A56BBA5E60FDF9BD79089C00F652F8A7A082002F7DE05A277F40D47B6A7A59051E491C38682CF8F894FF74C34923628A1B3154DF696E343438503C0ACF3D8101E95DFF80D03BC6923A6DFFBA96DA1E7A88E34B706D61F4560D7052C1E69832E5D7182DE1A39831A0BB08608BC47AAC8EC4DC625E60FDF9BD79089C00F652F8A7A082001D762F57F5B89C51DE8F7A7528AC5F0E1BBBFC8F2CF80EDAD255C22B740D9D6E38430D132D2584D2C7384FF243DE645AEEDF1B836CE4E171CA74D06A9A7BF1134266085206648876CF9D979AB0AB4FC9BAFC520B9D9AAEB2AEB513662DDC630E72275D472A7726D52AA106B8A488ACB3C4695A4D07F8D181246C63682B71883B29CE91BDC716A04A29046917E1FB2B794F662ED65151A693673D6E42281CB2D03E3130F8B8B1D343103C18EC66EE51E1F27894945E15647785CFA2B8E77C65E91F33D39281500676C242E4D7B78C214442920A048F3CB50724F3887E1D9F6A8235E50B515124774BF58CA2F5A5547D8442920A048F3CB50724F3887E1D9F6A82004770E28D65469093CF8F1C3BDA04F9D02D113925412FA434A12F35BBBE5712E7B1591772B86890550FB3F627B6EEC0F124390C1AB4A1FFF4756E70B769543AB06DCA51F2699FBE8FAA4C56D8FD9E8B9AD210B129B078CB67D72E7FEF11DEFEC8356C8A8F80D223480EF7B6D263BF2A5A8350C12EA88182736A432CE0EC3E626700013898990C953B6F8D314DC6C9EE8AC9B20A8FE9335AB3060AD065FE8F50153678E60D2EB666CE9A8ACCB50F8A727F9847AC4EC02C36235967F1A985CD5D5EE9803EBD7FE7EF339A982869029179EF47B74A3A628A22477E7F1B171CC8016BFF9337870F54380E77A967368974A17EA4728DEC7C5A910201B41567498F67F1BCAF46837EF3032876B744A04C4C7D5158CA7C5D55F17A2A4270E0E3BA356AAB7533E90C1B53B984D52C44D2F81FD0C4DD3467407B6BBE42EA079F25C9F956B2CCA870907B9D8EE5B34975B7E614F212B6FAF0C07F24549F70B93EBEDC0C99BA539E6B52ACE5A58692CB9AEF03A3DC37DF2A4E1ECC468B9B0AA28AACCEB803811C718BBFEDD4D607CD40CDF5E63F197E966EE61982C137EAC56CAB5F72CE9535EB7D078C7AF08BF317B10B440284F0AF0AE332E7BEC3192CF309C77B93458944A8945CE61C7A5ED5AEEB723E074DFAF4A96DB9F79F963E0B453E84F26EA4FFE140C402AF8A4B068E76390E2D9DFB89AF8C0C96ACEBB844334ECFAF6890DA232FE33F9434C00D271E453FDF8D323C5C714742EE7BE2299F36EB9795A38C89B5338DCFA180C55704DE3939F2622A2CAB5E60FDF9BD79089C00F652F8A7A082005BAAD6C18FD6510B4003D426C2CEA4415E60FDF9BD79089C00F652F8A7A0820098D66C77BE30F9D747FA4A8994EE8E91F5AE53BAE478FEFEBF97C577F718D3C46B0F2FD9E15F603E23954A5D30025AD69574904D7C263243FCF0E37051675BD0B6CA6934987282661AE5ADA8F71D786394F245366F689DC57C1AFE5696AE11AC84D44F5D5FEFC5A537EA69DBCE2A9A913B66881EBE71CD4B56D6C3CF20A2CA48B00A7E8DBBB8D3EDFFE2BA40FFC455168426A5BF96A379E0E15366AA92AAB34355872A15B108CB86E979E980F5D219496766DFE33D997C1749CF3E08FF045132EF3E1FBF56F521E5775398FFF4CAF1784FC936B988130818CDF0F6CC859C8A6294FB380809DE2A050A8F839BBF4BDA1F9730D85C4FBE95D57CA374DCB69A4FCEEB28D51E26D801D2F2959E88A26EE4CAF7A59472E258840E202546079771EEBA4E3928A3157C0EDD85607FCCB7EAFD00DFF92CD6661EB8211A450F6845D6E914C18B81526E08CD3EE90AA054466099A1F0A271A47103E0B645568CA606B3ADCF18391FA810BEC4C3671D4040E78E9E0ED5874096405AE843E52B72031AE66E39992B34F41013CD2BDA83195639EFFC0FC99B255FA8B22853A8F2F7201F90783F32B66292506124E9A272F3D9D12E42EC8C50992B36C9450C09E3702AA6CE86C7E9958E5ED53AB5D58DB22D4BE35561FFB6DEC4086F904C21FE3A74A2E59755EB0E5E83C9F1E64A3A32D4C6428BA2FFD1EF6AACB450D20789C0737D47D990899498FB72A789D7C81237AB8C450832E7FA6DADC736F99CB4AD82EC4D9E3205244446FB3D94946C71E8FB0C46748F19442A33B3B961567BCF752B8DA450844CAF110D71B9B65B10B73A9D0D6E0863404477DEF3878BAC3B241F74AEA73B9995AF0C416477FD905FA2CC57D7F4CC329A3031B2A8ACBC82811A38809140A8DF3B6B3A1E4750D9AFE4673F0FCA59971F7CE476A80BD16D50DB3F04112538BEE6BD1C5F0D71B9B65B10B73A9D0D6E0863404477DAD5BD590F520F65F7B0AB0F4805495F7599BCE49FE0D5D07C875DC3E4993301D7332809A05125DBF799487885A16E547A93A03B58D2EB745B6F0F1A69F698267E2FB3241B983857852785940165B33393A116392487B725944E5A4D225C48F8A1C03B32C6E1441E3750D991F9FB8C0E1463BE1B4342BBEB3541811A6AC1F53CFC199E9690C3284165601A8DC1030A1CE575A04502533F601900934DBD2382B07BA99543D782600DD65C244A534973B97908BC1AE96366DF60DAF1E62505BAB7FB88AE4078C22CC8EA76ADC1F3B0AEF0DC844CBDBCE61DC8FBBEB6E0AB6748AC10EBD6F04D3A22ED7737ABCA2C0F4A008B780C96228218F7A95878CE7E9FEAFF7064073CFAC019229F32D7D0146424C17AC09CB5FC3573E6449619BE516008C8716B9FA49227B74A5033EF12005B7625FD513D85798D13C9147B890F4885025B74764E783A13878DA8030E324D562C0E1CAD4C6DA6C63F463E1CFD00AC052DC760C937CA1F0E188EB39805A5F49CCC9ACD613E72274C91050E1275F18252910D5A4683470C799C21ED97C1E5589BF6DC1F2E9D8729E06F79DB2A0E4C84471D51DD7ED0E3B0FDC6E6CBD16066425A5407ACEDC76CD580D8411A0E75B96D02FBA0B882F43E0205E104E406BC207C5EEBE4DC45222586F018ED903D9EDE00706D94EEA64FC9040AD0BC312FB589FAD2DAD25EAAF8134C9655D890DDC632F20449C3BD3A350D2E93E273C409B99B216D0F8A7D90E0E66D433E244970C001F7D638726A50517EE17879A2F02F8879FC0CA264BC1D064ED48BD1DFB244AA34CCCB26FAE69FEE46506EC7EADEA5609B67D02C013FBB1CF135A814CF4ED6A0B25CC67F355DFC43BBF3E4000C12732DDB7807CD3E16D236FF1BA6EBB63AEA81822CC6071FA341234B9611A60EFF6149DA8275E822F81796DCC30643F93B357A308BBEBB3B39077FC5543AE442FF4363AC5C8D3C95A6602FC9CA4D37624510E1E112A4278A4180CAE2FE04CABB593EB39D972FA981FA3D8FF0CF46E11753B53CB263B674955EE9803EBD7FE7EF339A982869029179D5768BB7925E2E4461F44744C609D898FFCF63241054C2F170B777A06BFF8B0F1ACB355F2E6F8FE25CAF6C89EB4E232FB628F747D3532D69BD7337FDF0A36DFA7C24787ADCB7570B8BB4E79E3B0163EE025E29E24F72408A36862F581A1F7E2153797BE59CB698E6E808614C3F08C6B07E28593BB7345D779FE72B7C8368A1FE4549D544826121B8530EC46CC038A85424ED3E3E2F5F92316BFEFC7D51AF3474915A1A5195C5C578FE43B05C5F711392118E0715FC74D72113A1397399D11D4FF9D1B70E089FF91685FBC044365DEECDE35AC7619A109FA5F175439D902D6E5E5BF1D28A96827D3CB6AEC6FCC6F31AAC88677E9DCF3233F6AD1DB812982171EAB9568F3F4C642D26E0C3FD12ADFD9BD944A2372E1EC573C3C623D7D453C5AA768A8977E4B10E764E3DA7BE6DA48800891ACB355F2E6F8FE25CAF6C89EB4E232F1C391391B81B824267D675978E92BCDDA9F6C86046BEC4697F56E511C9F52987EAC88656849FF89E8499AF02B02120F54DA55C1ADA30E6D85A1ECF2C4B7AE008FB6AD60AF1841F862D07B3558DCE2D6A89B4960C577B6A120227D9C38FB82CF13FDFE86751B209DE05545BC2019BDBB20D125D1332DDD77E98322B42E743BDC7BC1FE61C7F3BA6871C0F498EA562243E7F80BBDDEE7681FCBF2FB31186BDB8C5DED1F85A7ED25EEFF0F033568188462F5B54743D45D07B8FE228A1A5BFF31670621A3BFED98D872836C2BD79E66CECB09FFD9BFCA7769F2EB7C660CED04317F85280729F6678FAB19B5FEF07D9553430871641CF1856A64BB16A6B9BF9F4D9E8FE88D3C50A7B10B9B76EF1E6A7CDCD239544AD6ABD92A91DDC846324EA81202593E5464CF37780D22AD8134A1C9165AC8F4A338F6D3F80076333DF7DF043DEF0497D3464F8868AFA69B52506319A96FFE4AD5446D7C941596B28C7147412703B66639C78179D261EAD9C16D0BD0F5CCD18391FA810BEC4C3671D4040E78E9E0ECFF950BC259099D7EC3B6D372674D8CBB11AABA31816F45804AA1F3FEA83CBFDFFC79054456F23A824B1B331B5797F86394A8D1B8D49ADBA7B99DA4C98BC0A8D75842E2A34EC077E10BF07F59EE57ADA42920A048F3CB50724F3887E1D9F6A827FA38BA0DB25ED5C55520ED7897BF281760AE3EAD73336013DF41289137683B2BC73E4C102303F0B8D9A91A1CD9B69F909DAC673FF888F3F57B08A3B10552DA00D71B9B65B10B73A9D0D6E0863404477C278C1A488CBAA6078F9E1E855C1D9E25B40433F69FB5A32B1764CC2F629074DAE9A9782596E893C77F512B44BF6EE7442920A048F3CB50724F3887E1D9F6A8270A8DF7CDA3F319875FAA1000DFA6F1B68364BDC5C8F5681456C24FFB7EECF44A41769B14124565166FFF4D223FDA14D8806707F3D474FD04055F1F7264F11FC852459F768D18935D7F133989B222A756E69491FB68FDF0D24611EC91FBC446665534BCEF47B43FF40075C47EC623B311E4750D9AFE4673F0FCA59971F7CE476A80BD16D50DB3F04112538BEE6BD1C5F5E60FDF9BD79089C00F652F8A7A08200F11ADB84810E827BB26BC78ADFEE8786AB1726001DEE4AFAE5E30458A8141491F3187CF63A45794509406245E49949495D040ABC57DCE155FC83595B13D86408F626D991F02DCA7AC9395C39F186EB6F1C998FE80AC5AA48A28EA58A99C8AE97F63D1011FB7014E9936096D5A40F7609DB30E0AA1864E520D112DA84023B14AC4DF991EE711AAC2EC90213D8339C70251A7B1EE7E35D5A27BE75D07E285D16CA75A9505B77C92D51DC6FAAC5F091344BD9FA0900D9A61E069EF30A3BF748B0965FCFA3BCF1DDC642C9B7564CCBD76663B6DEC4086F904C21FE3A74A2E59755EB25DCCB8ED4DDA1E58DB864D397758CBD5E254E273DA3D41612CC378BD0DFDA85F9CB3753D744C48126D331137589696B9574904D7C263243FCF0E37051675BD058DBABF65D79D12D2563D17625AC3CE2665B412F827DF6C42B77E9FC6217255DC5AEB180C2001D8C7BCB45F8A93643F53461C305D795EF4A190E400DB833FE767EB6A6185014CBA7E25203A3E121432BBD2D15688B183DD944EDB309EDD9AE37E280FA0223D49D31AC7F5E1F2509DE7F7275C0A097E6C1B68C91C605CFE765DBAE819D580F476BB28EC9587AE514591A1E5131BDF39CCC06EE29E3EFD6538885ADD06C19979BE17C7498BB7D2E6B4821C278C1A488CBAA6078F9E1E855C1D9E20D71B9B65B10B73A9D0D6E0863404477DAD5BD590F520F65F7B0AB0F4805495FE989E3BEFC26CF9E49F9AD2B29CBF809F10A2F8817BC1437DDD85A5F05FF398A52CE9F9322EE61CF2E4C076938D968A582E8C304F526C0CF1A6E78151D2A211275AA0F07FDB04E3E6E04530416D447FF34187DA0BD2937AC050179E66DE42054AD0E57597834E57EBEB42F05FBAFFE2018A2ADCB775E6BC8F5E8231E1AB2BE2516FDD0C2D67427FDF59059324455D63244D3BC5A3389A59061A7A7F6D6A51520E92F35C599656ABF843016A0BC5E646CC497A2B23522C2C1C4A6135083B53596EA660DEFFA0A7A84113071E6D55052D391087650A97621AD797C3E850BABB10B03E3828567A19D25308B9F5BF680B8B74BEACD41D43224452AC82EC6474C515F179AD82E785FB816CC990DC6D75D6EBEA948FDBFE35B05BED32A1478A2F506C6F3CAB0195F4D503329FB9C0B36E5D100BAF71924DDBABF5B8D2983ADA6F9D584A72CA386EB2C0D11848AE87F22435FA4DA0FC862B7C695D5935E5477D71FE1281DA1E08DB2ABC658BC7D1B964F2E6052521D57562439558F0A395457BBC57618968C56BFE36D8111FA2A1BE93BB218C1C36F4726C722B81F0D79125AFF9A88A6EE752EF7DD05313840D0238A30D624B2C8A9912D2992B0753FAC12A909380787CB9E1DFD42A50C539464FE469934C0F6AB6D59118D3F8CAC2A2414D044563844CFC1BEFECDC72D2FEEAA33EB485A75EF3281BE729508130428BAFA851983B5FC77BC77925088CA7F025A6B0C5849196DD2EB553B05EEE97C600EA4FDCA6BE2E1CDCD3E39F425B9FF429A748F301D66679C262E94E17E4F0357B8C2BCE76AD6BB30753D545C43D98E9CF7C4CCFE7905C1C3CE7CA658F5EB96A756300A357198A2BAA89F065C8D300B4AA1FC8D468DED1860D209C7E3F1692F2E9DAA7E65B35EE86394A13B8B95818594FF15011A936133556DDA583754EB8E3DA1131584C8358292E09755EACD4D0EE6FE9AB5BE65755C9A2C091628A0DFFEB31CA1930C3743B287423901F1FA1BF0BC968A80461F42B68B940F46A399B6FABAF52A051F9D980411B7904E5A3E5C47CE3F7A88FAAF04A77E3ECB33200E6F05F73FFD732D91C81F98610B1365F1C518D2F9612423F34D780543174D3FA1E39CA5C6D33552EB69E8288968D0685E5E278A78BE31BA8491B3F8BF7471A9D995081296D63EA84B6811759379B895C35EF7839E55B6B9C094A5E6B508C0F73D5770079E509179E3B06C0BA108C4821A1837495347B978490A2950D8679F9D2E5F28E4AFCC8890588CE3EEFDA064B1DFD5FAD10B1F9729EEE6698BF9D02B01BA3375E690FEB09F7241339ADC83B09C6BAF0A8EBE47EEB8696A7F7B9464CC17358384A378C9033D4CE1BD37B2B07CCD53076BB3D85E6066BC33A98EC1760121363E97A92C8223E9022B5F1841602D3419F64538C6E1456F6AE20CDBC9ECE4BA939B1994E9FE0A97016A6C4F4ADB860A92E78E8202B8A2B45F5E2D569E5082A683DEE79B4A53FC62C644D376971508F07D2EA3E4EF3478DF05D1E9893293C4641A048032A25AE0DBFF6AE710F0C5EF6250FDC82491EADEB3B416009508963EBBCCDE37D5F94D9516A83432DB2C5FE193B133FF7F1B6B40170B58E61062D7066AFAF43DA6CFF8D895D741DBCADBF52197AC2BD7CDD1FDEC3888E78AC5366747CF801ED5596D75D5392DA22375A9505B77C92D51DC6FAAC5F091344BE86E5D112279083A4A7DCAB20B1A7F1BCBCE2BCDC60FA1876477DF7D9ADE1C70B346EDB179022EB626B0D9968E6B67E19219552F52AA5EDE723D85BDF6D91D8259B3B759EACDB3CC4EE9F5A10F6C46E960BCB35EB12650A3ECD8C3F1BEC25852DEAEAACEEC5201ED45A68AEAB29A178D1B68A77358A5282714B3ADC25BEBFE16B9A445B9DECAE497F0EDAF61B556C3826DE9920F743FFA38F845645D9699CCF357517FF4D1DE9CC603B49736EC3B528EFCF38E82E3DCC60BEC159AE2C97B0C2C278A3D45A7CEBB3409CC8CBF11C4B8791ACB355F2E6F8FE25CAF6C89EB4E232F36A7A4A09FC675DCF40F65097705BB4539C4F190446076ACFD60EE773F5CFFCCADD06C19979BE17C7498BB7D2E6B48214A847FA43786AD2E9315D900BE7D0EF90D71B9B65B10B73A9D0D6E086340447727ACCF4853592A8EA9FEE17766D2D52F7E05C638A25D13F7DB462EA10ED45687244C49A282115BB647636B6B919FA909A0BC8E1E7C8735CD078610ED1F8193B6B5C787A2ACDAD3B62DC556017234EC75C489EEB86D54859A17DC86F1317E9B96A624CA1FBE149935D635F062DA0C936A2BA532967EB940BD9BD9F4D61F5A7294E511748D54DDDB9841F6E64E5E6FF27BC741AD3879CF9BDF7BE9314DECF7860B7FFC724208D20B18BFB4F34A7336C25A4C58FDF700232005025FB0DFEFCDD70905B632345DA245A861A7CE002B07B303A6719C60136B12068FBA8D5E868712C3775BCB7C0812C65E4F31D3AB6B81534BC943477121FDB4B01F74391F73FF140B9FCD184037F56BEB14E2F81E37EF9B940BFFC16052EDE32750F7E81D94950032534D28060C691BA851DCB7E727388CEEF4186191D467124A4DB0B2E03849DB9450782D1756CC3B9340DF667DC52C468989827A88E9D6766FCC0C47EDB9812AF75D511E3D9E82C2B14C4BFAF10418A692C9484D7B71CF38960B51D1FF4D1AAA1CC82B0D07134BE91704B9C3786BA575986450CFD03134DBC0F7D747D7423700E8F921E4C9EBFAC2402EBEC8C6F999C51AA341234B9611A60EFF6149DA8275E822F81796DCC30643F93B357A308BBEBB3BF30E921A95029BF8AFB794075653A37E8BF9D02B01BA3375E690FEB09F72413395CF21F72AAD34EFE157BCB2D07EA44031314698F4C2730A8CAF9A8B8DBEF42549C2AD57CE3B634EA18273C573DD0DA34A1EFDEF0EF70871680E716C2BDA0AD139D2B6DF65665C8B731F5D544207968586B67928CE069F20F82B29226A4E1E775126F707BA1E884CC09614C72AF99FA5FFFE478CFE94C52206DFE59FB90DCB640D71B9B65B10B73A9D0D6E086340447760E5366C8A3CC58B37E15E3073EBD5A0156B6AC753142566D2B0454992A3E2C7A41769B14124565166FFF4D223FDA14D5454DE9EF80AD2C3B9FA565BA91230D6B9A445B9DECAE497F0EDAF61B556C382724011FD4B21AEE00AA0F55DC11A29471B0015BF0533DC62E42F00F8526E5B8EFED2319F593666FD5821C7DF0054B661FDE9C2C680DB7A6C20E2A256D9DD6C9C1ACB355F2E6F8FE25CAF6C89EB4E232FD636795E0CADFB13DE6DD5BB32C13670D11ADDF96A4C9D136A3CF44E8968309D8C7878614FDB3215CC53D40E54049D0D21F64BFBC36ED23F463095F4D152AE559EFE74973EA5457A26D40D87BA0496961286216F59339381A59B32F8299EF6A93912F5ADE2C60F9E884C02890B9958C80817D822D9C45B93B4B0832C644D05DD720520BC351A22CDC73359AB3A9B8566B1D1E524D3F7A0025E9BC0E6FDFA448D922B78F2BD55319A6D58764AE398C84DA715057188D54F858B0FE27FCF255939C0EAB3649A6764D1276E569E5E71B2AC5ED235562BD46D94F8D0F8350DFBB981185F382B5EB8B4BECF4927ABBC16855368BF2C2686DFC7C49FBF50ED9B48AADD0B11EA4D8B5F0A1268F7188B509AB8DDA3AC87379BF134CF59841E03D7EF1DA7AFA852DC4999800E78A5A8CEBE6A5A2F5399DDAB701BCC9AB4B3D8780C5D4F95698BA6A01AD04F1143CDB0B17B71EEE1D4054D328DF0BF7F81FAE372337A42BA55BB43F7CBE82D2B47E21034CE6CD03653A3B1AE6CDDF7C31BFBAAC3113B956B2C47B30EE85BC778089E177AEA0DF0F6C26C846FF187D7BB0A733104D7137118DB4ED69497F10032ED381129B7A138EC81A842E9FF91850A8ED2766A68F65AE01D3EA730626C5C4E95D1CA07682E52B61CAD4C6DA6C63F463E1CFD00AC052DC7160F5615AF5C5BE395E74C82B2773BB17C912C9487CC73CA934C6D3063EDF3462B746626DA7216A32067632E297F3DB06CD7A0071D5B6915B78F5D10C5C475B312C35E7BA546252030E173B7242717BB0B06E4E741E18676E1038A77994A0B45902AF66323336026A0FBADBB407A671927DDEC49B0C3B1F641A6B4D08F8414D02BA21DA43D910524AA88AE7B47B9C5E02C226498F1ED7C2AFAD7989EC4983B33D71BA686A6ED86B98A8C22C1FF3B946D49202737FE6799D0B798DF6014347DD4CEE0985DB5920223EBFBBE79109EBA6A1DA7DFABBE8EBF361122299F1127B35806C940679B8F31E87073B3DB44E801689DCE391AE7F767BC04033A9A7A0E7B10DA7D1EB39E3E6DF15370CB56A18A109AB6C86FC9BD48FFF88EA2B8E6C32FB754184A9ABDE61F9932BDA04358FC37231CF360B2311C22253D78FB0B0EC4ED0A97A15E9E17BE557357D8BAF0DCCE9D1BB42FDC8E7B0F3B8FAA164F095942287163A628A90D10C588156EC752BC31DCA6AE3AA172AAEA09BA838ED3CF4AEFCA78AA92538227A671A1EDB062B31847C2786FF9DCF97B394DE7AD5753E04B83C8A0C7C7883E98DA520307FB59BED3E62EAD4BD33D61716E63CE1F58D2439D588C6963A3B7DBA201AC8527AE025DE54818ED4292E2A877869F32CECE9311AF4E80AB3E84A8E15CEAD204665337D7DD5FD42DA97D18D906F9B75EE5FF5ED4560FA0AC0068A505D4F1A3270B4EA716D49A5F0913245978A39A1765B3D296DD425C138B1E7BF5E7ACFF8FA57571618DD2ECD955F36DE3931FA9A4EA10EB4E490362E2905E9FB4BA4BA328DFB27DFE90814B13256690B62CDD232B04DC476CCF26582F40E7C30E2425E781C912F32FD10D1B1DC67720E160CF40576BE8BD9548A0926B2E922DB49C46550127F1EF38DD43ED893B8A82A0A27C6B84310CC8B6BE62ECBE07E0B03095669C6A29CBC06C77A6D2741EAAC217AE5DC3512261229A7675376393E4944DBA2EBBF50A3D1ED49E95D266A76769213A8E0187F13E1E68DDE775BE022063E9D28531960CAA3A42848479361335A36BFD9B1E31E040477F831945D380EB7A9E6A1D37740EEEC6BBEA78E0FB6E7413AE2AF23953E996F7F3968C8994D0795E60FDF9BD79089C00F652F8A7A082001F9D9E1C718CD4EBF04A7A6AAD40A84C220F1193058B89792FE515B60885F4A989D0EAAB995F49C705EB4568A3515CAE50EECA7862BF57DE5BB290F5266ADAF620624B48B4F02DA65998DC01E7C8B19EB246CBE2B39A726B68FA9D18F9FDCE81D446205C9743DD69AB3613C8A5CCB18FDA05B8CEE8B7D81B9ACF15A2470FD9A8A87A7E9DEEFF4FF29E542FCA575B05B5D3EBB881FCCAE04171132FA7A678F56E62F598B75CB4B038446F79FF50B97C83E6A8EC7245CA5FC2DB9CCE780F1DAFB942072E99A175EB3B77DA2E09390EACFCED8B18FD682CCD38A2E38863A4634C844736D3613246CC6E7CCE0CC07D05BBE02EAAFAA2204285EB1D3A061D1E93CB8533E9CDC1A4F8BAF11D3C6BDFE89DA48376A9A3D16D082D038B5B70B346C0822F93E5464CF37780D22AD8134A1C9165AC8F4A338F6D3F80076333DF7DF043DEF004D46A8ADD10BE658F9BBA4257BF32C0A9204DAD80C2B38EEF63A42129C557CE92C3C7668A7EE101150E9DE9335673BEA39CDE89907BA478D032C7B392357EE74BBFA6E71F285EBBEF7DD5938342ADFE86E5DF932C1B0462B5A588C35C7C6A14D859660D2629396EF409B1B3EFEB1957E456D3AD82366E5FFEAA9059BD2279871CFA5B461BC18777ACDB71F9CA5BE0D79C3AA9E295E2CD60C9C1A33B1796271AE09F0B1EAE9F0A6EA8FCED201D2B024BE3FD9D52B4B7C870CFEB1CF3FB9E2BC6BDEEF881603BDABCE9D31C4F9E3E1D3141FD50BDAC4C891A8008D64CCFF206720FB48D4D891FF655159BE6187F357E7F794E810C81FDF60B69BE3156EFDF90C166E76C544EFFB0956D537F174FE7AC11FBE4A49FCF5FF42726259A7A0E692BD347440677291FA9F1EF9436F6F615630EEFA86EB6F11D6D74B07CD117401474DFBD877BABAB3112E0E6331882A1B9B6C1C77A29750E30349DA225A784FC9B6073727C23C16ABE2C524603BA2CFAE9F16BF6D92B008BA8831782D9893612D2D0B38A901A6D4A7FAAE3F99181BF27511FA611285A9DD8635204F28C712D08CF45DAEA8D2951879553E1B1571D19995B657AC3A4EE9588FC06839D451FA315C113CB78FF576A45DC8A13BE145BC452E6A42BF68007A9468E5730527FE677C32799A312872EDAC1B872365C009A72AB0DB4CD261F0ACC50F8C730197383F44097189CA5A1E488604D529262006F3E92991251C06B8D640C47105C1C28E54B36F7DEAB0DFB5DEF026C3A1035DF6A667B8A1DDEC09EF2ECDCA4AAF4A787028CAA462D0B8C36450E10D370E0EA9632EB57B41D35A5B8CF74F3C0F888FEB231E1FD25634B6FAB9B78461C07B2EDC7B0AC6E0596F34A6B8DF77C686B99F73899E6175899E70A41E48B2DB15ABA07E8AD548C3D9F793B968AC39A9CB173423C4FDDF47570908D72135EC67FF0C025A2C2760E0FB31C8A29DB6D79AFBB9EDC32C8E3548181E685586535FF84670E1D44CD202F3464BD880DF723E8B6773B9EC29617C52F1C3844C0FE7630976B1529AE41441A8F8BBC9183B1AFF817EBF79E29745002788E872F22D98BCF10E4205FDD23FB8B4D07C7B6BF6E4EB39286390BBA78AA519995C0E51BA66D6B3057AD5F70D3FB09EB111D178F57B3B35C967E88F8128242546004233972EB9F7B3817F2B07BDA5A6E9D54CFFE83A94339EEB1E3EA834F4682EAA15125A0E9F00D88610BCA6C37DE8FD81F60445DFF7C004FA55A22D82AE4EE4D7925E5953C2FC831887F33DD308CC86B2934B53674502DBD1764734933B0E54BAD11910BAD52D57B7682688C03FFC928249437FBC9894D74B9BB556A33A2F5F9FEFF8D987AC1167768C538CAE2B7BF6B9A703E3AC7DB2671EC1224560A3302CB6E26F7175A1F5FA8FC6C43C45670D78FAA64F174593763FEA5EAB4E53E523B30A72152ACB360E685B1909C02FEFE8F699672E707AA0A5A1833FCE59899F358615199FB2EE19C5478AC6B7B4F32D6312CF1BDC12F0913367CDB233931C1408A73BB6854627BD622085FC9E230C58F24533A562815C5D3B29969DA6B19F4401619C7FACDA64641B740FC3959102F8D5FA38137E83DD6E14074485F2F4BE13E2FF274583AAAA0E3F73C2048381834DEA19D6A4C9C0D12696130D17D4A7987C8B6740A065055B4D707F3F9B2269B0BCE3D20DB88B7E5E2FB1BA0FF41F100FAE35FAE5D2C9893FB773922C4543E94EF33EAE432BDB53D43D69DE8A9C2BED249F6BA469EC46E5545B1CB64F43CE77FB458BF4A310C28660DD531370710F4932C23DDF5F28A85CFF245D274F39550DCA1333A6B609C870E814799A738657D2DC7031B7C2B16312576E7B14DE88F101FAAB272508CC6CDAEF0BBD1B8C8EFE86D0192932C9F21ED793A9EDEF199280CD73C24BDB7CC592C03B2B49415984F84AF0AFCEEBFA9211A1DE277729D30D067A5AD1E7380703A772D35B5BC72456DA149CB95CDFB4ABD3BA1658741FC15B1F183F12792C861AA0C1FD8D3C56B972B04CD6864DC6663B1849467D991D079C37360B4D76DDE14E8EF65565DC72B0CE99E3000ACBB4C6674009E466044C33CD3CDA9EBC5D14D0288B7E5E2FB1BA0FF41F100FAE35FAE5D2C9893FB773922C4543E94EF33EAE432BDB53D43D69DE8A9C2BED249F6BA469EC46E5545B1CB64F43CE77FB458BF4A31A54884EDA0C0944A56CB153BE08AF53F936E9D1AF033CBE78CF44049CCC3DBB4E2D83735C8CEC939D2606592F955A872F7FA70469E1525A02CC85D40CB2227B6B53136A68C2F8B380325B9EAC9FF8487D950634E568679E4D2AA3A1E2D4CDB2B6B48008EFBDC7F6B9D54569C4E3B356C056D71F0E9476B59F91CF87ABE7B1CB902C376CC876DD6D6C87281A5352C9AF616D3E550B0FFA1CF75D4F9E7CCE882A43851D77E1DAF045496A519D6055393F8656A0225D3DD5C88A8DB81C3ADCDD0FA9F114ACD9956FD059963D04A0F80B406E66A3073F7BFAAAB757175A1AA4AE5825C01C0F7DFCAB1E7E983561E3C02B11B1E646D26028EE4A809EEBB6D8D00304B3D9505C31C6B1507B9DFDAC12B6B48B1492CE56C92E7CD00CD009239407F48BE20FCC596E07449223352CC149467E9DBFD89AD65185F0600A5C3B2EE1DCE0C434F39ECB9E8891C4E57A78B3CDB50EF3FD882AE1C734956EA016FC65CE252769208C2B02101299882A042281B5F3CF6B350F486822949579C7EA6B1F74315348777618AA400B077BEF0AFF12A4993585B71F90849530CC39DF061B159F4FFDA068602D2FB585EA1AEBF72140957988672C8A9596401F947F7AAC66A90D4D129D1C8ED07EAB0D58D7B3B3FC42A6AB2038E39ED3BB5325493E56B2B8AB2EC3C04617917AFEB9127C2395F4DCE61E71592538BD78BE82AAF0A26877EA79A07E85755C4E3C60BC9C6BB2CD59B0CE0076C0AEAEBF5CF8744B084EB6E970764C9911BBEF6B488424CEB22E22995D5940A8FE269718EDD9774AFFB6A0027F008267AEED10D60FEBC76EF14658AF318746FD885EC6F446E252328C08B8890A4AD8157FD8DB752B15CB0B5B0B6A26084D266B18AB67A2631E9E1662706DE5FF1C080CE451076925FA90DADD72942180F19BCA16AA9A0010C26EF99E8B9718F90210DA5D6B74EB44645F6A92D9C89A1D6DD7BCE13D92152ACB360E685B1909C02FEFE8F699672E707AA0A5A1833FCE59899F358615199FB2EE19C5478AC6B7B4F32D6312CF1A77660EC219CB6A463C6D997533AF56D6854627BD622085FC9E230C58F24533AA5681701A12F4B75DF79614A18F208D8304466B3E3AD1631BA46A5B10BC23E9C13EDF0EEC008012F7F96B9999D36BDCB0D741C580C00DB08FD52B10E7DA8206F2398CCE0429C47357EE98F435058B9ECBA307AEF6B9CAA576F1891363E8EC5A98FE6C01F0500E19F8CA3A5A90B392FE381BFE0078D30EB2AFB6FFB311099788F81CAA53998C2CFAF63F6241725D8C8A9AB9D74CC665C417D44FF092F6334BDA0C7291974FE719DBE616DC854213BE5C759A892D4A84AEC3128FA725AD215610F7A52CCC0E4FD13AFB50A14A9B23E6F538B7C7E273A2439C81C1C6799529227388B249EB9C964E7D675C711598CF364275347CACC707814DD4B8B96CC915F7934ADC823A7BEAF4AE2E10083CA50760987D75E3B7AFB5A85526E058250FFA0B0F5BA9467CA90AF80FC08696361D9BDA2B09BAD96FC1912C71D3C45660F02C9DF993388813A9CF4FB56B5B6AB7218E6C95B14257FBCA7F53CEFB0A118042E6C063AAA574A79BBD4E86EA828F6D459364B6B69A2AC85716D0C2F3391B22BED7A30390D2F559DCC8AFB26202ABD6007A655B059178B69DBAA5CF662C419C135FED092043B7F4C878EB5096CE6029A2BFB075E01C550F5581DC44DB6F438AF50FE79E8D05B493054553E86AC4B3F20F5DC1C8CF86BF831FB8C0BDEC227550D784602100BF1E29AC17BE19827F0D2ADF75E1BD46A779CF034B00870E6E1B91276846852C3C60890389716933EA0D0F0B393D27206DBB6C2CB58EDFAA27D6E67BF7EE04D54A262C87F3348B0E79050554F2386146A5584AE0D25FDE17C4EF2AE25FD47C6559707DD18A2301C4492C5D099EE4A3D01505BD1C26A857F135462950A86B95E203C67AE7862A54C55AA44EFAF3106BF6F11D613A93BAAAA39F83C5A3380AFB6CF5EFAEADF3E007993E1552A47A507EBBDB2C0E4D3465CD9835C4EBCA65A437BFF1658DEC6ED5890B61B37658F717030C454341789689767B0A641DF07FA1088D1DEEE25B3916E75486218EC13D0652C18D205B69F6CD4801EB699B3FFDE9B467AC09CB5FC3573E6449619BE516008C85961EF15FDEB06FC5A2E9048EC4D0AAE443D48421EADCF682DB8C3C982FA01652649241952D6B366562F7905CF89E3F31F2BE14E1E1A97CCDA8720120C05FB8FF66E9709E36ACC9E0115559B55DB54B2B1A598697D534106E608760996EB71431C87C27FC78594CF6332885E11F489933A2FEA2718E24E913DA4063D0C7770F73EBDAF4454EE3FAFC36EADAFC9B639C219D685A588398AD9171E3900C59B8636B24A7D5621565FD81EBF4D558AB79D3B242F07D52EA2E5D4DB5E6E1CB0E555C65F073735040B2AAAAE01BB20813D81613882736CD227C1BC2ADEB387F7BDD938180985AEDDB94ADEDD6D80509850B06ED1ABC55318078936F734E0739C5D126110D55F672CD4406AB1E8B0CAF75A198A3F102024F7F0FAF8E83840E82B40C23E15C3E7BBE90799D946802AFDDEBDFD76B4FCD3F0B2B08C1D689D9CB877BBB3BFB4910A9B3F87D148A940F4F69AD509E758171CA9AB1511A719D32D0DDF46114353684C4290A999809D8E2E9B490335E8C4C566463F9F957F3E807452433608A748894BB349806A5D52B086105A9978A1BF4AE393ACAD454C3A3C50F6A0C9C4F8BBF98AEFD648D114827BFF6C1ABAD9B6FD5068CF1CFF688F01D04E2C84CFF3A3DFD7417F3321DDDA43C4E618D9266F385ADE27CD213571C100763F9829367B19EC9090D02DDB462416E4BE0C511E8E28277516463BBE0EFC6DD7BB1B34E01D9FCA9E1AE5C12987FDB72D5326B49D72D2B0D333B758402962277D6DD0AB9A00FA3A0A0B0D5906F0ECCF3C1B49296E695D2D7BAAE8AE1D5D6C19060C0D1ED06F6ED5BA4EDCA9AEAB5B74E28FB797DA9AC6BC580B946572A14877EFCDF155C8672139A1762EE612C804D54FC83FDA1D98047618DE293ED3373F55EAAB6B39853C5E642273454C174E8296F5CD7C69BB2545820C78A70BE4E27A375882F05C473E008A1E76D5C22578AD6166B6452195B29AACE2E3828F05860836204222D3D3E2AAD59DF19AF793A2AD7151E038EB8E234FAD7E78F62CD4412D44C92D978900583FDF495FAACFC8CD66491B6CD2B8FD6037AC42210471AFB554225E508660D46A651DE239150D8D7161A8198CEE2C439141F74D87DFE052C6938980F0E2547ADA486FD2C39926110B6F96AA81856829F084A4AA4419185AFE81AC61D7A4C2EB08507E28593BB7345D779FE72B7C8368A1FE134207A8DFF70A58B2645A1C5A04B839027F79B81AD5822C81DE9C1492AF6A5A99C6246203DA5E9739848509F1CC448075A8D820716CB2DAF2CFCC9288C27C26D554BFBFA23316DE9F20F95C01187B638A5E086036C981976DCA778C974939D5218D905A7BF6B7EF35F891F45F6B5A967EFA91D293DD49E9E1D7450722F594692DCAF8A732EDF309884B6DE87B5FA3FCF74D87DFE052C6938980F0E2547ADA4867FA973DCE6822ED57403DCC25CE89D52686D7F5184D9D4FEC417B4594D5972F7E28593BB7345D779FE72B7C8368A1FEA69748AED23148AF13321250E8B21FD9027F79B81AD5822C81DE9C1492AF6A5A99C6246203DA5E9739848509F1CC4480E2EE15D4802F9425B28DC2B88A09201B33ADFA5F8EF7619F32CC0B2E1C84BDBFDD5DA623D60BFE1EE7AF878B79BBCDBCEBB5C1A69D903F6DA5D89287D88700B08C3DDE8C86C211A776F2779D056BE964209554C9BB2F65F9F582FCAE6743112844E02BAE9FDEBDDA79A49451174B82D2E2CA184FA69E014972FCB221980BE3A2E9F64A221463704C4F8C816E4BDC88211E6E737E029658B989FA40FB5B04231E39EEF0539B2B820BF332FBC22C9DBA80F32DA57492F5DBDA7E203FCE8005E46EC6A19E8B04538B99EB11E932578BCDCA68A095CFA8D01C36E2858BD601EBDCE59966B4AEE1FEC7FA38A18E4C8526B651E5A6CE3D2A232778E08210386DE5446C9BF27A9E62485755783838E81E8D3E2C262E407AFEF5609F406C6D2AB41E8E644E4A99BA0BA74BAAAAC6D1D836DF8B37662D6D29BD84EDD5B660C52DC94945F6FA7A19D0C8811B0882A3675A2913A7D9E408F7FB5E7EF5667F94D928D932197F7C9346B2DA1B8CF76C6F1BCEBB60427B3B4DBD2E8280D6774A0150EBA566F38DDD6357436E7D69B285EAAE0197C509ADE5A6CE3D2A232778E08210386DE5446C9BF27A9E62485755783838E81E8D3E2C262E407AFEF5609F406C6D2AB41E8E649FBEC5446C6BBB8FEBA04E3F014FE13B662D6D29BD84EDD5B660C52DC94945F6F4A8C37D97032DAA44DCFAC7FB2FC97AE408F7FB5E7EF5667F94D928D932197F7C9346B2DA1B8CF76C6F1BCEBB60427B3B4DBD2E8280D6774A0150EBA566F38DDD6357436E7D69B285EAAE0197C509ADE5A6CE3D2A232778E08210386DE5446C9BF27A9E62485755783838E81E8D3E2C262E407AFEF5609F406C6D2AB41E8E6465E580C53A246E98A7361EB4E83DE9B5662D6D29BD84EDD5B660C52DC94945F69134AF3A4D94BC06805632D6AD1BCD4B98D7AA96B23DF79DDCEAD3A9F786D7C8AF68EAFFBAB437658BF4DA274D6BA1A1E6E42161B5F27645B7E78770FFCC726AF41E70577A77FFEE25141233155CC0941D655193D0E73FFD5F76AA7D7FA757573CF0BB7A6931618524DBAA353143C3AE8B708625E303D488C839C75ACE73FEE4539749A9E7623D67B284B75C536B7B66350147B6177E836960743B9EF8EAF7B277F202B1C5EC39224F8CE1C6E3D92328EBB5C1A69D903F6DA5D89287D88700B0FDB199AD08B26058EB277A16EA86041A09E1DC1A2E89534C2AC41D17D552CB1A80CA849D7EFE23C60A820F5DDD19A8751050D6B582EC5CEAD818F1E89DF9D87E8968189CC494DC9E02CBD1FEC9B7EFB6D6F471B73116ABC48F40D87D7DA0143CBE8256A281DEBBA09C0C8C4A5E546DFC0C7D05DAD886935E8080006F4929EEDE6D84BDB256666A87780007F8557804F9C5995697933DC702F83E9CD9FD4CE77285B82F55A5783E098726296F13272D6BE2A909CB41315317E0B68CAB469E0084A1C14874321846970A47A1DD14356AFE897954B2DC1A8493719322D58541B44B3F3505D4541F98B7E841CFC8F2114BC0520A1F667A531084E0C785B7C5C985A4866F95BCE7C8169B8AC2D08A3135CBA60ADE52DF0C714F2E56AAE8188934C0B318D089527621F11054CC5674ABE8F1E5AE6BC6DD008790DFE374CED9AB4A39C0EC5CADB836DBBC6A0CF0BC5E22F0D92EF114E6F0907945C4E684D8425EDA693EB7038D63AA21E1D55F3321DC1CCB54A5A93B257C78DC5B50DAB7DBD8B2AFBFF7BF45E7138FACA3F9EE9FD2CB446569C459E3DA82EF132F37836D32282327188D61837EA701A086E68B54504B6B9219E538E7431BA0F0B85379B778C9E97D596C1BAD000CC3581663937AEC417799BD222CB605A276A14DED7B7A4F57BCA5D538E19B2CA1C6F9561AA1862D30F3BBCF9ED9F5661C226D9D2838C831493EB568BD410EF6A579E9D2B6C53B8D72C1E89ECCF6B4C22ABD61C1FD4166325473C077226CF0AD18FC177A95E056AF7AD30D2FF07CF7FA4FC2799A4B0F16711537CDA51801F457B866D6851B1F95F82CD92D7B59D84EC11A6FBF9BF31CC719507E4B7412AED6D6BF0D9132BBCCFBDDDA4D333323C7883E98DA520307FB59BED3E62EAD4B15689E00C56317CFDA0B91936CFC7A87FF95B3E1FB740E639BEA12DCFDA24EE74E0589F828CC587C6C396CFAE38C9C7912872EDAC1B872365C009A72AB0DB4CD34657B0A3AFBE31CCA99E1EDFD1F567FB2AA773D0039184632CAE32BFA178E446F4530D9B6506FDDBD7E0D0C9A99BB654EB5F151558A6A322FBBAFC7B1D9688FBD983E2DF567930E6DCB47A0C4859A7C72411C634645F1F79E2B0A720D7E5B2EDD6AFA7885680FE43CC9B92DE78C909887E2AC0739A2857CB01B3105F88594CB2E130E625D3DCB6EA87FF486E514B77D5743DE2FD7E67C60060691EF57F87EC5C9401095EB359D52E644CC268E5D156D42307EB4B055702C3BF0BDE33C3B92BCC14581190510E97255A604700D0C72D60953180F2E1C653E8E084091C72A7B2C9FE52A76713BE11AB2E748B05A2B54CA8F9D031320F978E744C9FC16E3D397F093D5015996370D0B6BAD6A13B49C35A6643B152CE29A27691EEF5A918F97CBF8F9D5AAC77535BC55716E509AC698B9E2DB3825A20B3AD0DB0B20BFBD030BA183B651537D04E877D3EA85E0CBF45A0BBF59BFDE01FE51136FDA8C73D039A4FEF648CF604D3B596C2D7FADC67DCF950F4F5C077920AFF9DF7CBCB8D8D9C72856238028F83D1EA67405E689B377F067897E16744EC2DB544DD86B502CF55044166F489CD9F34F10A849518DAEE8B4ACE87A48381CF0B9BCB058F77884A98BE9292B1E21D376886D3E90C183CDE57094590A2C438AD410B7BFA7500690BBDB73C254CBCE2BCDC60FA1876477DF7D9ADE1C70BF35A1A51C35C0FA9A9E962CCC247994E0E474BDB9E0711DBD2BFED41AD3AC652A51BF159A728876F89B2524CECF9B1A908EA76CF52654293FF9B6A84523E7887B32E4E9C45CC12DBD09C235F68F71A0A3D480305069A194741B073AD04B2F4B30DEA7752C64E2E514D6334F12EEBD983920FCF2EC469BF966DFB0E99C43C848CBC686282D7473E9ECCEA37C685D602067FEA229112D1C53A5E108FD4073F39016325F3F6A049AD82984F4AEAC51B6981C34A1C33496ED4305FE760972AF9CDD5D374B2CBBB1BF4CB51422C2EC56890AF5ED22F9CA95974ABE455AF670D371F92AB7DB3A47FC4864AA04A3D72A30695C64490C4E7419B1A620095A88655E4C78588BFA29B3DA20215A90BC3690856A1CAC4E12A6640B45CDEA7A4488DF5D924549D7ECFF8F4AB05C1C97571F83FF773F70ED7B49641B4F56FB8EB60A271896FD15CAEE19F89DB12684ABDC7A721CAE575F147F9A3E1C7E45C5FF7ABF6C25675BDEB839CCD2B9DB51A26D85608D3281B0DBF0D5814FFF5C9C7021A5FFBBAAE68CC5F6E80D815976DEBB74D704804D923C063F9E30321E70E90BF3E5B7C07D0E723160380D5E6EAEEED9D4A549AE684C9C9F2AD2B15B12DE74996072C803AC48DF8FA2C1FD5093E65F1FB4BBB6BEBCEBAF2F1ACA0BD4F6238EE59BDA4D6A95AE9B9B149575B18E61F0BF94412D49778174492757BD36286D71827E83793E118A310D3D51BE57F59579B084D3CC6FA4AFF0E4FF202E08CA57C0AA876CC569A95C532CC849745355216B485E4ED90E4431DA79C09D2C2E967AD674C6940598A762E50682F6EFB130D2D66278FF8B357933009025742F2CA9A175299E6127752695E4D7888E8951B433F0F863E127678A51D6ACA2BFB8E1707F4D1612C35E160172C681B24ECEC50AC5C69C019564FB4B8BC0A39809A80015AE4F87F1201A5BED1E189EC78C2535360F0F9F0643CBA3563CB01F0960B05A26D5E70384D904D294764DC96CAD4D4D5F6408AABE5F2D98877735B4E899F51188A977A2A0579B1DB0681557D337ED6E13F42A9D4EFAFF6D60BCF794684542300970A295BB50DC52A04773F0438C9DA351A50F7C8480857E34424BF91B03C2F4B86E0DCFA64A908D26AE646CF0AD18FC177A95E056AF7AD30D2FF09B4CB58DE74B3D0764E574FA1DFE6BF0CA69ABD09F0E51ADFC3A0C0C831BB74686A0C66F10E4D23258EE266CE009073084E4EBBCCE322377406E056C12C6E567A18299A780C0709825D878A65F065DA825556DA8EC11CC6C7477B421DD3F4BA8CA43220143D5B3E478384FED669161DB3A394BB33823110D20387313DC05B13E8F651AC3A11F6EEBEB16DCBF962C010C142085EF529093304121FF976A6ADC71EEDF1B836CE4E171CA74D06A9A7BF113CFE5C1C0B4394A3F95BFD5155DD0254A1D3D1BB3B787513641F75BC03FA53A127B5A18B6CDE1A90C42AC63A2242B3BF4FD87C016102BFB33F4B384AC1435D1A250983E6835A9562A55266AD700D4DF3784E4EBBCCE322377406E056C12C6E567A18299A780C0709825D878A65F065DA825556DA8EC11CC6C7477B421DD3F4BA8CA43220143D5B3E478384FED669161DB3A394BB33823110D20387313DC05B13E8F651AC3A11F6EEBEB16DCBF962C010C3912F5ADE2C60F9E884C02890B9958C80817D822D9C45B93B4B0832C644D05DDC2A53CFF82D46390445BD507F709679D45892692C65DA7BF395EC7780604903773889371BC483F652F10A22BBC0D99190F12D10097E78397869459904B301F625ECB61555702DB37F96E6A98ED2A39367AAD775E650B279D7A78A2416550AA0CC689A9EA24C4CE181AC698F9E3D5C1626FD4E38FFF45A0E5D02787D3768E9F01444824405B0E37444095010B5B05DAE8191E3BE64BEE55D7FBA600DCE013F160363D057251FB6DDF5EED7445430940ADBA4DA1A835ADFD183B460E2EFE1FCF1437070AA87685D7DE7A4D801C3E7AD260B92A3BF02C42331681A1649CF1F424963B5930A91374F0712943657DED8B88D41003C3ADC4D47EDA6D4C81A925EFD39A652F0132558D66A04513A6F848A31292E41665CC36E5D5C049B2C687612B872FFFAEFDA052918638B1169DFB5067841C68CB5235B9058E6DB6375C5E5EB5F8E7A341EB59F13457ED7AADB50890ADBF568523B36905140FFEFEB3B1BB627251A35400C556D590809E1DC376BFB2E70AC3878235719E283E4F998DF7987FA6EB620C0027B839BCEA2E67A0FB7BC4674E744F5B173AEB4D454FD026F763741EEBE54DB5E2FC8FBCDA997C3F5BB93BDB201CB87BE285945126DC3B3761A092B09864FB8AA755EEC56D2CBA58CB30F082A86709A5DAE13C9057BDFD2EA77460A47B08271B2CA885F7A8109AED0273E91A0994DECCFD46149F6E96793C5FA24F3286CC8ABC66EE6FF7C06FA89834897743A78A9B2A13C1B59EF002C3F317BCEDED1111033444245316941F3CA82DE63E6509E4C50B1B4D6D9A10FADF2E1E33F607425A916376A37B594615CAC19B27FC29C8D1D3697C8973077B68CBAC5962828E822F64747CF05D960DD68E0D8E58873C2D0EE94CF799EC311311106CBDC8D12D1944359DD32C2B936D74D9BA0AC2D63E812A1AF5146352E3B42BF63F1C4720AE5B638EF99BDB795F61BA33DC8BBCBE33EB812D35126755BA23D8E6E3FE54C87A29B24E86FDC21B68FBE93073FCC1B8912E3F46556EFB22D271DDBB7A890CFF0D8AF94A5D9B8AB01BDB2AA0336AEFE8603C930FC2BF9757041EB19D25D1A9AAA24F6148915242866CD64B0CA9854A72E2F85A5D7595F034E2FA5351EE6FB7066288B5F104FFC21F5707D57326D2EEDA5A581783733E5573676BE027EB10F240A405A470A2CD69DA3CB401D655F8630057D3F9211F1358B910750EA40787D382A6FA3383AA3E454CE9B7CFA35E138BBE17D9DEDF243CDA5B81F8EC76F1E06AF381EDDF33DDD7C11368E00226295BB6674FD5D885E46595DC10056784CE6E52843CEC62661516C10693D6857CABF9BDFE3979EC85E0358B5544B055D63EC2E2CE691E304BBFA6E71F285EBBEF7DD5938342ADFE5E60FDF9BD79089C00F652F8A7A0820099944766620F43E24C7CDF0E6B3A9BD757ECA767F83965272848ACA250E6E6DBF47F198C1E38A95CC946154F0895A47B2CB14DE8F5C7F8F73C9817B571BC053F2C9D7E4D9C91BC221608DE4405D271F195FE1F4392999D66F9B0C2489FF2CDE0B47CF09FE775DD06959376365C1DEA7EF124390C1AB4A1FFF4756E70B769543A56FA4EA6142BA2633CB1C5B6C5418C39F8338B3F17C41D66B13133B63AD907FB42920A048F3CB50724F3887E1D9F6A822459535575D8847FE91C9482BB2571C45E60FDF9BD79089C00F652F8A7A08200D7306E1A5D137DBDBCBC65E9C4296C1437E75FAAA0D6C21F054F129464330F059ED2D755C80D9D275E7E1A8926A72DD6E08499552B33D333725D435F45BFEE2F0C0319174F8CF4489051ECE3608862C987858E86D5027E94A5A727388E47399FFD02336299F8898758A77334A6BAD97C6930EF724EB1EA3E2E1A473710054C3A7A3ED97E24D7FE1699A6C774A6F902E463B0E4C93DE3ED6237B75B49EA417D0C9A4DA3F67FB8FC2E9C3EF90D906714370BB0F64717BA060346BCF83A61F158F052D702AFF4F3E50B85126E4E937E985C5AD48B41E3C6C3384B29093E89E951492A9EB9C3F1C66DA8BFE7946BA9462F4A531D18215C7E5E68A5296A9888F0ADC7D47942F9F19EB4A90878C5B32DCCA3DFAB6732A07C6EAF38239B24F1A94608AE641E844B489BD3421C261AB7B9ACE01802715DC836537F1163C3B50261D2F95F18E21937A53F7FB1BA102CE4B60E99EC4AC5691ECE57700073D01215732A1DFAEC4A839252B6CC4F099B2EBC6CB52F413DFC59733196E9292B98593E595A8080642C1397333A6A72521CBD55A167C2AF875B8DA24F44C6C62CF4BE436CEBAD05E1211392D812A1643A3F1B62A4367872288A0B53618449C6C398DB6A29607975D0FE892594629A4E0F704B28044A94A423021A67CFA0F4714F77C524CC872DE38C50992B36C9450C09E3702AA6CE86C7AD7E78F62CD4412D44C92D978900583F3D0FA3FA9B280CA8872E58DCFC0D8A50E29386D5C8E28D854389DF46B5EF0332B5740CD79EC81D0408C046778048DC2D38FBA52E008ACD6C6A1A218D5BC64FD0EAA82FE8B9262CC211772A65708CA82BDBFD4D356ECFEFB2C5DAEFF17C138103B777100662AAF54181938CEFA105A97555D0929EC9E35EE580A2985315B9414E4A1EFDEF0EF70871680E716C2BDA0AD1E01329303675DD375342154202EAB0835E60FDF9BD79089C00F652F8A7A082000E1D920DBCAC2D3797C823E2D9752FCCF124390C1AB4A1FFF4756E70B769543AB6CA6934987282661AE5ADA8F71D78638C658D68215FB7C145EA1AE4A4D1BAFCC6262A6ADCE2E2D7DCC651F99ED8F5D88B721B0A7D09F5DB16CA9F9C305FD3D04A7B548BC3F1A193B0E0AC29D3CBBBF14A7B548BC3F1A193B0E0AC29D3CBBBF15EE9803EBD7FE7EF339A9828690291793FEE933D87DCC7C2C0B5D8FC391E66514F05C79CBDBE6E43CC6A933DE6E71C7D59CC6D6A30DE3CD64C982FA9BAED986C8CC1EBD889D805DE85197B1FAB829B539DB1F77BD75BB7563C3D4A92D203991A491B73A8E2AFDB9F897497112D8167379DDDF14B42E8EC7EA441AB144AC3B33D32778F1791BAE64BE34C4AED463C8B505FBF6AF568E20F6F2BB7F20CF76F82D3CD8AF469A72E690FD385CA898AF3D006F2BC3441B8E6C543F04FC776B7159C3EC1BA9DA7949527990056BA367776A23DFEF93924CBB922A2DE93C2B88805412829D0AF0684BE5F48B26AB39F8DB046915B54743D45D07B8FE228A1A5BFF3167095D9F5CDE8058E79FEA503DCBD715DF7D6C572CAB9A9643247F4C348F046EFEEB4AA96EC22D16BD5BDD5B94B43BC711B9AF0412F50D5D51A95BFF2B364363092D4878F7CAA096958953427DF62AE49EA75B4C6A0E30906843FDAD3725D1295868CB7BDFA49CEF53C10DE5E2D717ECC0690BDB19A50C4D5855681B29099750E036465966E6787857DCBA418805D5E394956A3E57B9693C125129E78C2CEA1E1022A765C117CE4C50A81FD411F16A024B71F2E9D8729E06F79DB2A0E4C84471D5169654437E1C58962ACA7EEAE220D1DB14266085206648876CF9D979AB0AB4FC985E9F20FA0A1B3992FE0B96254F3B04C81DD23D3D261C9A09E9D5CE8D982FF3504A9156E9989AC6C5EF325854FE97C2FA9F1EC748B198A27AAFC300122315024857EDD154AA69A8A1B0EC5F4EBBECA22FC1FCC52E5AEA5B40E7BD6524184C9D8F214A465BBB51DA2524A14EB8319C8F90308AA4FA6D0CC632D85F09AC9139EE7AD0B486FEF8F79F144FB2B1AB45CB2FCF6B488424CEB22E22995D5940A8FE2695E60FDF9BD79089C00F652F8A7A082009E08C7F3004159721CBECD1391B189B18535D3ECFE76B71581CFD36116F69AE95E60FDF9BD79089C00F652F8A7A082009053BF3ECF8DABA2B664AA8F1A724CA25D114EF47BC52C5E24B87C65E9F54AA036FA000988C12BD1BB8AB11B5A12C0940CDC12FE46D4455FD4254F3BDCB81F7F5E60FDF9BD79089C00F652F8A7A08200CD7C418F25983FC0911A243705860A783FF5B3DD682F9791C2896D832B2CD91B43007E36C8E9C92792796EB7BD6940A83D18F83B1BDFC7AEFDF506268212020591B72350E45E64F96C882E65C728D29A81DD23D3D261C9A09E9D5CE8D982FF357D10AAB0AB0342F6B39D5A2BBE60695DA50579A219B6906CB461A0DCDFB1CCE2292DDCEC03EDA0EE704AD3D813DF2B2536652B5AFFB4E85C33E5427075E94DF5F124390C1AB4A1FFF4756E70B769543AEE9A1B5370818786124F6832761FC26C04D3B8426D0E53A5935BD606C37A5EF0A5F9236859A40F7825916FCED1FBC2C581DD23D3D261C9A09E9D5CE8D982FF35A69F7CBDA0C3E8DA2696AD6E6A932B8A6EC14E00171258D01C1B704CDEB646DA6B310611A575EBD9B1D696BA95955152BEFA489F6717746E78D951A02B0017E695204AA40B905808D19C9669C10B474DC72AD57118A3FE6AF29764F410A3D943DB1016043BAE3C120F6B263FA12C330C7069FF062C520DD732B8FFCD8933AFDCB88BCE8869DDF5159F92D67058A582A72B9B148E4B775AEFF316BDA34C06499AC21AA16552CFED8DAEC6B2FE6A89BB09348F64B8E792674BC538C4030CFF4EC603180D60AC6D2687FB6576DDAB6813D475D24BC619D6CDA5BA3F2D8D4A7B08EC10238F28DFD9F365088F967363690A00FD8696FE14D53C65C9EFE55A92C60790D61BAC7247E2662D770870600AA382EABDE5D8DCDF501F470B2D99A093E865F626E9279FE1FA66292309B039F2489E67F124390C1AB4A1FFF4756E70B769543AF6B488424CEB22E22995D5940A8FE2695E60FDF9BD79089C00F652F8A7A082007EB429CDC69284326413D037BA0108D5F124390C1AB4A1FFF4756E70B769543AF342A63F79D5F59CFA514E7DEF3ADF38995B2711DA8DC749D4174A231009FE365DDBDC080B8EB834BE23577DA750C6E0F532842304A11E0FE16C19588E5B14B15E60FDF9BD79089C00F652F8A7A08200AF4A463E84E48411449918C67B7BA9F3013617FA333999664F82C5FD74A749989CC5841AA9421B316BFF5E16C0071AD9846F9A2C3EFCF19DE5DACD396ACB99ED5E60FDF9BD79089C00F652F8A7A08200B21FDA68506DFBD72F9A4D7BD9CB907E3909D0E2793CBBC0209059D1CC435C9D1093D85B2E85FE2EB569022C231F4A515711195B5803FA447ABFD35AD3D0DC215E60FDF9BD79089C00F652F8A7A0820073516D40ECC872E864FE7F081EA8EF50E06C4E1354FDAF4F30A5045E7BDCA44D5E60FDF9BD79089C00F652F8A7A0820018C7594DA46BAFAC6CE3AE35B656EDCA81B06F12819F4BF66DFB84CD5DC211A95E60FDF9BD79089C00F652F8A7A08200453644983C4B10318BBE34527A92EF2E3E3130F8B8B1D343103C18EC66EE51E19EAF7D87501ED3531BD62812E43367A9DAFBEE28D1BFFEA00F8C32919F1906ED5E60FDF9BD79089C00F652F8A7A082002678D6D437A6A894F44DAE4BDDD4A2EA9E2CECD26789011A807B2968FDB35AA426E9279FE1FA66292309B039F2489E67F124390C1AB4A1FFF4756E70B769543ABE669352DF8BA54E5E1656F1643A1B753E6A6DA2C51E93AE0F39D0D2545026F01C14034081E13C9E159C6F8983C895E042920A048F3CB50724F3887E1D9F6A829BF27A9E62485755783838E81E8D3E2CE8D49F6522C7B9D298CE19DAAB3EB498D9F5661C226D9D2838C831493EB568BDF \ No newline at end of file diff --git "a/spider/catvod/\350\223\235\350\216\223\350\201\232\345\220\210\347\237\255\345\211\247[B].js" "b/spider/catvod/\350\223\235\350\216\223\350\201\232\345\220\210\347\237\255\345\211\247[B].js" index c2dd7151..3b24d738 100644 --- "a/spider/catvod/\350\223\235\350\216\223\350\201\232\345\220\210\347\237\255\345\211\247[B].js" +++ "b/spider/catvod/\350\223\235\350\216\223\350\201\232\345\220\210\347\237\255\345\211\247[B].js" @@ -8,4 +8,4 @@ }) */ -3F92FF3221E86493981E0E9FA6A410616FE9D82B7088F2405DA1FF5E3DA4CF8EBC6622329A4F10547545E251D92CE0208E523028B3BE3D239A96123EEDC4AC8ED7C157CC80EC2E3A181A70E880FB204560BCB2D2BE90489208C325AAE1E36B143C547422345F38259B04D9FF32C086990A8C724956A95ACCC895AD6894F7F7112A7E9CE8A8865653E53462717C9ABAEEBB19D2C9D2D0D9E5F3FE5895B8542AEB9BD17047A1E995F537259F7A9DB3C24CBEDA4885E0438DB43CA61B8C2421F38F36532D52140E33DEA1A93658A3C8FDDA21505C74ABDADA5522FBF056F2B094156D04E6DB178D2389C73E0CDCC98636B87231801E9077C2EC540EEC7472B916E932BB22AB80711AE3E9B91B6602B6ED1BED66C4BB9AD16275AD6B3824215FB382F46169632BE5FC3B13B1D35E21F267BDCC78910C0F11955410B88413962BB54BD5C448F8CE50D01B0D46AF57C760D50BA8876955C5D9D3AF363B784529F73C30752A7F66D4BEDDC2D2B3117066170EE700F9062AA94277D4702B4E6CFAB7A89C6C7EBAF559FC2E1E3710FD5ED233289EAEB65FE6A5CEF6D46ABB2F20016055F6D89339E9707A5E1E3FE9A36A3B089BF3CAF0F5F1A6D33AC33F4E6877D8CCF7AE980A19A1E08DDD378013FC35798FCD7DCE3DC83225D624A2874768A0EC501831F1C781CF038D479E37EFE0CA02D3E2074C548C9D8FF175386AF082C58B0CCB4831AFDB93EBD59FF7D436D0BC5ADD37CD92792C47813E5DAA3B0E62CA83CA58AEF5C92816347276C75BDD5B07E649721870D4539235E39920DBE530FDC64B41E475EA35864DB72EC24382DF62D273D1CEBBDE06795C8A5C89F0582273A1C8B8B47A83F8BBAFAA20BFEE19C30D313678C1581F6553C85DE830BB5AF252D889EDF0084D5C5EEF3D0A381FF503E7CD6C0F75D5A23E149E6DAFA28BA04B7233280F6B997F7EF6FAFB334D8A5A1C1918A7DCEF34CA042D8046BAAC172F66FEFED1E533E5A12EC42C8243872CBCB7F6B628442542A9BAF5DC3FFAB465D883D0C95DD6CB0CC3B26C105988590566E2BCF10811CFC77F44B57E8871A71C17E7CA73B36BC4028D3A898888E4AC7CE3F1277CCDDEAAFC8A9D1F74C41FA851377408C8F549997353945A39590AF9E98D0740B1C9E63606AF240A8F0C0F951099CE4133E4B94D8E944652D320A1C632AF79F60B70ADF596AFDF6DD63B1B1BD088773731FC1148A6104FA9B6E64296DB07150D4106C823DFFA03826F49918B176A0BD22C7708B2E8C576E928711FBA0C4EF7D94AE56C3B930CC698436827B6273EFC1E92DB4035DEC1A1EC10412D8DE59E689070E6B2922D4C78883C584028D06876144A2F745D8DFBDE8A5AF44B9FC85B9491BAC7801D89B8020A428E54A4363BE83AF2C57A59984ABEEA1E554B2AAA2F1C09AE71730F8DD70E423C4B430F17FA34E0EC58BDA6C851CA30F5BE1EDCD212E2ED16418F322D928E464F1A0F758D72C5876E9A2F688D66FBF3BCF4CB2C21C478D11FA55F0C5BB055A00C22A7062F402AA49AC1BCA796ECCE2F12D6B715FC0C4863F5907A3DEC94354432F71B5820C5F726E2A17181F2D60222DB4FC8BF2098E2ADC23017AB7B0AE746FDC279B8A0267BD93BC3B03C6BA50E4DC82A968E5000B21B7CD9F6C0039CAC264BD8BB51F2B219659A3E06785B539BB96AEC0312B69EA13C2804687BD263486A09C5A1B87F394A2D687C4CBFB39C19999A6E43052FCCD3A88BCDC1556EC6C87AC1E323CD8F3055BA13D583DEE043F40DDECAED3CDCE364AD55132E5AA0DE957C34BE6C320C9B8826091EB849E74EEC8B5C7BD369A59601F67F2A4965DDBED6B7E7AFCDD6B4F102A2B410C29A7395952988542EF5D973B77CC76F2B03B2063F369DF61C12D8515F0B6ECFB5E0E284DB2C93AA4B7DB1830A89B9B1F04F9A7CDAF3E2933B7672A26716B96CB4F24B3122837116881C614077A4D79237C9394D5040D05544A3A6E7C17C3798CE94293872FB388AF0AF7C23D6CC66F0E5E1C17BDA4FE8A2623CACF86312C660EF1DC293C3B2ABE77E750ECB413BB726FAAB0FB16B75A8562EFB13CF8B31DB167C480F7370354A0E42DA6645071DC1126D8464039DC90B489A7935CB262F26CAD439901535969B28E7516C04CD4DD03E2EE41F83C3C8E7A53606293F8FDAB2BD922A4C521A4F8A9A3AC773A1FB865AFD55C79A874ACE0B911E9E4E6C8BE677252AB1C6C5C412E3BC69235CAE75B5F45B7A589C8CE9674EA65E243C16E6013D9CF3CF8685A88905382E8F4D9CA6F53F18822EEFF2F19C357C9764A25DC479E528997FA11890BC3CC3FC351FA98D29B019A1EC69F221CFAEF8F9DF90E6E0D3775897EE21D7EB4EEF4D4A2FA6E6F63E20F7FAED36B83FC6118BF3A8AD5B8B7B89004BE9FC38968F135451042DCE277301A148E0A44C5F8740A9C8E54CA0E36B39DEDD5E1BC40735E93B2165B150E591DA46877E303AB4FFCCE8503C682B924CCD9B6BD37B2AE72BC1B2C3D372918AFA9C4BC8F57E7C64C1CD320ADD140568FEEB21D030086A518F04F0C310497E375140A8ACE16998D7FA572922B6710C7DEBB3FEB88328C0E195EAE62BDC4812EC3026A00D460F794BC1438E9A4F151370973BCD53EA5486E9D2AB1A110DA40A22594626A368B9130980CC2F3AC117AC7B42599EFE8D7184153AFF979548E700E4D6C89244F7C8BC3AD1CFE29C50722096DE537AED62ACC29265895F6E45B5475B99F1C1733DFE42B7B5AB3945944C96653F16EB903296F4BBD023C42112B27C2F68DE9678255B698D64D355E5208858510C8C162C2AA036C75CE6180F44959FFA662D5EC0DCB47BEA7C86CA8EAAA99255BA71A0D39E947037FDEA953E5F72A49DF2BE5EC623B4B0116F81DF82BC6F8B767ACDEF47724FE58EC5284C16C52C6E58F2215E38D06AE06D03FC7DB9DCBA13FD7BD64A56C2C1582668D031F776A0A6EBC31AE38825706A62742DE8FB57D784169D7F4A74EF6DD1E8DA366D7065B862A82A8BA71C19727350F2064D6F596690EFA9BB77D46015B8BE657E23CB98B06B179139DF4CA04583B39989EF156465FEFC227B3D908AE077BFC4BC6FA3EE606D18B5B811FC8AFBA3087EFB653A0F9BC015281D917A1D6D1A9CA450220B405398F096C5A47134231CE3A4A1E8041714D0FAC9D2250426C7193C674362B1F577237C8A6F4624450CE441A3BB2DB73733B1E25EB5199969B3F09F024D3E1C068188DE5243A677B3D51108F4BE48BDB5166644D11973D7C194BC6870870AE067FC144FFAEE5D714CD413B79297BEBF9E368104B59FDF53D647F8B9CC276835B0530F323BB431BDA3DA2B04FBEE5B9DE2F4C5D4E34291EC1157A068606F2269E1B5242606B10E7841A491A0F14E2255F2D9A5CBD5A9AEF93686A0131CBA1AE015D18020001EAD5B7CF3D71AA372D15D9709232E56B38FA9DB2B3BC96EED276EC5AC01060BC88DD660D6A9DC95B94C6CED6045DC19B9E10B51C2378D37336243F253BF5DCC4E4D5D110B540B04BB7D3ADBAEB817589AA41E985EAFB414CEEB2F84142E4A56D5ABB2564DDDF2E767795165D048320E1C95EAFF8FFF21691304FB8245C8A95697A5787E0C2E96FAB1FCB9BA6ACE352D3806C36096BB1EEF963D5FAC00734D3C9B7DA04C3C6FD5D55D2A21251E30188692F2BB3A13327882990EBD0DCB0EB778238D672CDD3ADBBDBBAC81DC4F9308856D4CFF5D682B06FB2863CF49B0E17BACDD0D9D2639E1281EF81939F820D8DFA1EB50158AA1C7C376B3E4D8FF9017B37DFCFCEF075EE0690831882192B496EBE3DE45A73EC8385D447E131FBDA15B63261452A14D2210BE37AD8EFB571724CFB1D2CC0D273F4961E352D72EC24382DF62D273D1CEBBDE06795C83F1423641295232F3285B152083F6797955536079608C24E901AB2F835AE7E5D274A75A6504B35DFF4BAEF62B60413F7E1F577B748DC7D5A4E2826485404BBB98184FF497377667AC8BA5148F947B7D2273E386B5171DD2B04ECCB9DDF6F72388645848802FC1DC2FBDE98627811E6F8D3ADB253EE4B75823A0FA332E018E6170C45364F3CA1F2E27453C71501AA69542C5A06C807356B94524095528165FF1EA7B0E0CE68B412B12382837BF9FF31E0E1FAA0F7A345BD9F2BA06718E5BA63840C899F36CEE933439F22D5684F2389FD9424C34FCC59909CA6E5B54190926ADC4B893F5D3216D5C7FBD7DA5655D557E5DC5B04CA6F4DB48C7F157851E1170DFE34D5B376B09A1D5A453F8223A65BB1E0E418A96889EE51F2B02ED38574517D32ABEEC58A076D33867152E5B74A59A08438AEC2CE38C40A6B5653D9CF5957429531AFADB0B559CFBCF62C5F3D65768AD643A42A9CC5FCA701268DFC8AB610253AD47FEF539FA4BFCF985A50494B5818A2B40CFCBF8D1AB4317377953622032B85D2E1E70B8F1C06DBB02229E161A67FFBC49885701C27374B6E34EDDBCA4578C58429537AB9C088333BC05E5B74FAB8871E719FEF8DCA44AB1D8FBA30D5A904CFF0B065A0470C467DE68271DE42038940B0F71EAA507FAC974D4C4007EC0962DAF1BD72782C0C66BBBAD9327A8AF744809D52E954127310E63AECF32EAF0D11E4A863E2D71BD3C3FEC07F58928C4D42151440C241FAAB8731640CD64EADFF6EAED5C9378D3B989B5AD323CBD0C08ECC621BDF92D050763C17F128179125A00CF9AEDD8AE27AE0206BF632905E1556CE8030E78E8B44CE6102614FF7E5B3F60C00E6B9BE21DE60018A04D765020E90615F5DE0D417F88F4DFE24A8993D94727353D3665A801FA2842F02012294ACFA16B558532A10D5C1301EF6C23C89026F293E02EAD5CD3D7A0CA44397221DDD3A0B872BBE2AA7F4D63BCFDAD9542835ED9DF4A6304A1D8C9787D893B172645DBC4CCDE4CEC4C09C9ED30104961966F0A3D54282A4E2F5D13B65BB77F80745FAC6BC4AF970B8F45F50D744C6B7F39A21FEA1D64A2D1A9EC44C561E247DBE4427CE2271A347E60CE7A985DE5FECCF04657C6BB313DBF0D6E886634FBFD4AD2B2075C018A4752314C9A10150314DF6FED7CD84056D8D96A5C1683CCADED7110BE940DCF6882BC69B7C9AA62BC2885EBB5DAC63133C83A2F0C00BD5D5F4A63A3556F5DE934338C5C23F11595BF66C80124883C651F030ED98E5FB1AB7B90B9741044614A112D8DE59E689070E6B2922D4C78883C52DEA2F750D5AD5F684BE4C3F8347ABC876CB846102EE3FB32C2429A38119F5518DCAAC8F7460A347F7F18E832C8F2EB4813E8390C343B2F6E682D5F0BA4D37F56125BBEB8BBF0528B409FB69F9E0C2932794233E057BEA34C6F7AAD0CC3D6DD93D0584F9FAA534BE19017A9F06DD2F75DF0A1E537E0B2D6148D059553DF38D410DEE4803A20FAD190AC195727BE3ED9F4D7F525C4D93FAE5DA0C87A39424644BEA1E95D7D220333B70F003770C1CD59055F155DF0254666303772892BDA3A8352794233E057BEA34C6F7AAD0CC3D6DD98043145AFA4D8E9D3E5C5AC3AB4C5B67CE7DBEB165BAF85930C88F4364BCDA6E2591F59C6131E036836625E7C9DE3E17E85A0C72010F2CC8A9CF0AE1A517852565FC4FF19F36E86656210043F91ADC6DD0F07DE70A76596D9B77C116A4A1B2D51D81CF0790A2D7C7A99795CE577564726A8DD97C44800E434434897FAFF87EF17800217EC6545FA2974D031054849B779F0CD47BC023B505A864DC377F2E02DF2794233E057BEA34C6F7AAD0CC3D6DD9E30F48A84407A67C5F7BBBA7E0C0CDD768378DD8FD17D6E09B21E36EBED1E1196EB0518A845F051DAC4BBF7689E93DB0C0F38CC2F1A6EA289298CA28F5C17E100FBCA45F2876670E25D21C3BAF20F3F72794233E057BEA34C6F7AAD0CC3D6DD97F9115D7C4CFA2DE262A281F745384134D5B6266AB3F7F0A154C711702E1AC9AE5398EB0A14A661DABE2945FB4940125A8DC6851249B8423965C3DEAF38C5F7A5547F0BCE88C86BD1F4E46AFC812FAEB2794233E057BEA34C6F7AAD0CC3D6DD989BC37FC3DBA7B6EAA31C3C8BC865AEF6A8DD97C44800E434434897FAFF87EF151905065D2D33214A8729C9D42A4986F85010D2685BA52F27B12E8A10A8E306B2794233E057BEA34C6F7AAD0CC3D6DD9B6A9A297B3D36FA6984FB4475D385C34B5ECC98BA8D6573F6F5DC1AA03C537462794233E057BEA34C6F7AAD0CC3D6DD9E6FD3436A64E8AC92D6EB92E78D3FE0E2794233E057BEA34C6F7AAD0CC3D6DD9A04BDA7B61ABA36D15A1F29EB14CA512AF78ABA7327974D9F18B2906CF3780D5E44E4487BB3ED7916539C9D8BE4E9C4F7A3D8032AD39CAE9C0DA5F6F8384C9052794233E057BEA34C6F7AAD0CC3D6DD9745F606B50CA9B4127028913A71A5D7F25BD42B4C0281563AF6A1347C60D6159CBA8B72F680F565911FA53670F927B262794233E057BEA34C6F7AAD0CC3D6DD9A77CE927628B7F8EDF39C3DE8A1040A3034FBC27845D446E7DFE547C536D8CB1A66FB3722840B89F7CDE8D956BB1CB692794233E057BEA34C6F7AAD0CC3D6DD925D32FCFC1DFDA8D643F023A73F48E50C4BB1A09DDCB3B3CC9AC57BBE691CC25AA29C79C817D8F0848A610F0AAE1DA3F49136E894FF821D3B71D8EC57748BFD013AC65A9B526B8B6379E17D1D04CEEE7A437760CB8B0114DB2FC46AA97DEC15495D284F66D822BDC574881E2E3C197614ADBFE8ACAA62DBA54AB8271BC12607B65FC4FF19F36E86656210043F91ADC6D49EBC526C343C2BCCE9E1E8340604AEE784E893D5136BA855B2AE7492D7C04BECBBFE7F18B4088A6C3AA3F981B2CC2E1BDCCB835ADF0426BF23F19853694CFC8813E8390C343B2F6E682D5F0BA4D37F576A93AF75D76A37EB5AA12C8D5B1FCD5D8661F9A8DCF429D72497CA3EFB6F0BFBF522CA41DC06CDDE92D11E6ECBEB889D23A667197E745578A67320C9A9E1431B9F194F4022A8B7BF07DB9A4DCEECAE9C5649EF97BD00EE644C1C680C064E62F518FF5862EBEB6055D0B81F01613C21EA2A51B42A727B26AED434760783D23635AD9C7E21F02F1262B7031471A733BF54BC5B70693B5C07DE49205A27A94BD07EBF9E368104B59FDF53D647F8B9CC276E26A08697BF2C0B1C6E37942B2098F16ED4BA80637AB0785699DE3B509B20F2FAF17DB68424DB72922E759B4FD0EC121F3C2FC7D226F52AC80EB0A3D0875C88699FE82FA0D261BE3FDDE85B1877CC75C69715A11B99408718C4EB4DB41046C94F348C0402B0909BD52912E98CD7F8B97BF813517639A4A11C218A8806F9E90B5185C0A7FD6D16D7E7DF75BE43A76E4BAB4D5DF6FF91C3AC473ECF56C9E0D3E1CEEDF3F98CB9CA912071F05F39427ACB2E7B11D7F812650FDB0E5CE5B6216411B88DCC94599EFC456F482ED14BFB907CA1D95E144B4410676DC45DDE7A0E2099FD07178F8D8C5E27E8E48DA962D5B7E86D33613216BF9A8C606FCA2DCAF648428CCF5987304BA8C9F0650D6249EBCB3147D3F5BCF02BFCD35F535EBD2E3D940B34F4404959FF7E9D54B3C620A28F6691211BCAA0AB97E57CE3CF76D1E573CBB3E813E8390C343B2F6E682D5F0BA4D37F5E26E8C434553455043005FE24A74BD2B2794233E057BEA34C6F7AAD0CC3D6DD9BBADF90167BED043C26F779A9ACCD8434F4404959FF7E9D54B3C620A28F66912D45989260C8C22878748DB383D6DAD7E660BDA6A4E99569029600B9A54E04B662794233E057BEA34C6F7AAD0CC3D6DD98398AFF818E5BA3A590AF18A8C86D4B4E1DEABDBD88A069A86BA03DEF75F8879A98C2FA02DAE5B74D1C8A9A99BBEB74A5C072B714A8C5CD55ED38D3AFB2D1DE8D1ABB19E7EB63B6B1F9A1A1B887C1AAAA448354F312A90DE22CC0C544E3008A6430F2E8B341272F6FA1C1E13E821AC2132755BD917CDD2ADFB882825222FEA6B5C105CDCE387E7E975415311CBAB7CE3D66351ED93DDC1A29CDDD995A176B22076953AF98549FCFDC13C2060EE15AC254358330AF37862378491A53A9C169AF931C47A500DC5DE200E7E6D1AB79F25C068CEC6B9ACEC1A7110F6750365E4051F1D44DFB0D0398ABD1AF262E51C5A5C962E315B15003C6EC7AC2A19F5F8CC8DB3973657683030A276486734307725BDD8FDA2B30D77218281D0F48F07694AA14F16F5D1C5AE0158BB9B7FF7B5C28BC7FC7981C03387FDB02926C92A09A57A0EE261146DAFF060FC10F5511D3131F7C9188F09D5CE8C76C326C7F34C9F76FC915FF48FD0E7BC838DD9FE89049B208BA72BC783C60E7C0012FC772165B5F0DAE38A9BD9B9A3252072B9181CE06D76D5DBD568BBD9E450E90040E69217E49D0FEA77FD26378E970BD39A27BB382D9F4617A9FF41597DFCECF7292C10B10DF8AB39FFD15908245FB6092E1CD9CA70DDFB5D21D7506B5CCF1837E6DBDEFDA744B469CC96933C7FABDA3F61B0D93E407DF09E2B0C79D3C9AAE39605826A8A58FB70538A89487C2B443720E591861F1366F731055A112CEA442C3893F598507AA99D46FB2677F98A4772E2AF1DBBBD8B5B3BF4C75CFCAD6D3B2FC57C19EFC11C355473E10CFFA465CE43D7D9B5AB4FA3431B7BDF459B395815FE10502A12CCCB417776F8F9E4A4DB11ECC008DA8976B0D131D95734E177A4BE8BF61D61DF1B0894D1472578E3BB108FA00881673268F55A9DEB9585B78840FCA20C5B38C0B00BF44A443B060DBEAB897CFD9D882C0B1720882B13532A51148369E0D0D86B63C79B933060C3BF7D15BDB873AC552E07AADB0076322DB450B90607D1F0942E7ABE156C2AA1BADF8F44058E9BA1A12CC5583ACEE9D8F7B3566EEF2999F4CEB3E5EC21C9649B159D004962DD953FD10C4405CFF9058DE8A907DA6C4F46D6F819B90B6B3E8F8CEEDF3F98CB9CA912071F05F39427ACB2E7B11D7F812650FDB0E5CE5B6216411BBEC20D0B820340516A19E8E9A585527F363F9DD57F9F3C6A3A3AECE3F58C0CF6A0D93519D3B19CE957DDF3A8F0E6A1488A73B903EFB5CD8D41DED8E04106944523CB2AB43392F85E3FE53A33568D36322DAD25E72996D241E570BC14586C5D9330B2E659070D0D1136E41314477324972B7679BD44E7079CA4A9466296FD14E5E7C24F40342D12B5028362FA74ABC7464A93978E1BD384AA6E7DDE0A4C3DA51116E85B2DE4070B8DC4BBC6F0F2258AA508AEB5C2EFE5632A2AD10CE95DA5B09563022A9FF225045E7FFCD11D7B76BA4C74D37CDFB7EEE7C670C8500C442D90FCED000C497DF9164E357F4D44A1ED9313ECE9DCD313E05E6208DBE36518D755372794233E057BEA34C6F7AAD0CC3D6DD95D89767442BA897DB0068686241E148C76E21E06A35EB58D771AC039C929701D9D384E54A388559067347BE6BEAC47E4103DE71ED34D643C0BA6802EC2F41D05634763F6DE7B23199D042E7A965959E9CE3B9714D9084CC02F6D14439A48A8F7CF31887BB6A54D804DC3FF72A24412FABE1B9DB91FB2DA11829FE9F0249DA052813E8390C343B2F6E682D5F0BA4D37F5A648F9ED510FBE70E31EE00E49D8A9CF7DFE93D9071A6376A992A2BA811812938371FEB79FA7612AFC0BF26E996B90858349D66E3174295320FC8964C1AAFEF912D1E48A91E6EB37BC0DD2CBDEC564495BC1DB660CF4C6535896A22EC3E647DD76E21E06A35EB58D771AC039C929701D05A713A22624BDC051C4D8D547BF817D236FEC79DACE71B0CEDC37FC3ECD1E0870E4E32852F155DA7EC4D275BFED0954C72FDF8EBB0108BFE9E0059FC1B51BD2C85220F70D6D8915885C606A258FEAD7C3BDD695B61FA3323636BFAEC835F7EE2C7A12367C5A48103FA3D158EFEA827179BDF44A8A2539A486577C018AA42C8D4200623DD88877C5FD7B6CDF29ADD14B0C328BD85B09A5E35149D4967AFCA00DC351566F9755A6E4FFB2B9E6C34C90AF126A37581AB59B182EE357F8F514EC973E503D52A27A9EA2A114CFB52573CED6F86750293336F4DC6DD1F1FE9162E24FD70DCFDB07B881236F5CB4E98CC5328602C500ED9474CBF316C8AC2ACDB5C9A93CD5EE664FFAADAEA27A0DEC7F458A91221B6030A1F28B022EB78FB41EB692CA6A8DD97C44800E434434897FAFF87EF1767FAFF1347E244B02428819D846BAA37114C9C8702C7551CCE3E7CCCBD20885AEAF473E30708778B09C9CCC3402E76689C74456A07391322C3B4C7F5FE313EDDDCC4420E6EB75A158312E1D1E6537F5F48FD0E7BC838DD9FE89049B208BA72B70195ECCC102DA4C8DDD203F7DB9D14BB66DBACAFE2590702F5C7006C3B9523BE80EFDC3ABFCCBD4C5ABF1A79C232829E68BE4FDE6B4D35B8363BD90C6AD50D617BDE53DB8F374B0D24583C60A63F483372D19D5C35D9C289294DDEB6BEBF9BB14280C04778684A662B1A73DB3AF45136002CD048052CEBF698CDCE8B1F07E0BF48FD0E7BC838DD9FE89049B208BA72B26D4AF0CBA360ED78065EC49D1FC3814CFE5D139AE3CDF962CC65188CB46DEBE30B91B71AEECB7020C030FCD6860E58388E5A08808756FDD719828033C4A283317658D4A3E089CECCD5129448A0DCA6C1741BF6FB616AAEF42C5E6C824DD408FDE06870C61DE9081F8ED97E6D9FE7C9872F6299A68FA8CBFFEE636A13E24F423AF3CF8728A8C6F33EA12AE4A210D3161933BC03D99EFBC6DBE326B5AECDAC6AF3471936FDB9E4F9FD475AB5B7BBAF5E4FA8CA4B72A4D3F5DDD256E405978F3C2A0D93519D3B19CE957DDF3A8F0E6A148A2422D2988208C302C83A4FBE2AF11765C10EC414DE9A2DDE7491F0FB5D1778A273E386B5171DD2B04ECCB9DDF6F72388645848802FC1DC2FBDE98627811E6F8A14DF48C78E078A017C11E85CB5023490C231827AE5DDB9C75591AF4559ECABE8F770738C896DF7BFB24BB9E369B6DC853840F170B1887B89A4A4F3A67BBD2AB994CF08D27D0A14C3969F6559D7476D65822D6506CC8357D724927E396B6E972C870AF2A79966AF7E3B61E53CBBD8B620200D562E4685D82D49A7F7C569F1B2C90301199632EB339171D1AB276D173F2A30F856D5D0B5BB055442F436AE9A19629AD21C19052A15B0862F6C135ECE7F25FC8646C05B8CAA6B9BFAB8661BBA7268A75515E61ABC5A96D5EC3A5C9C05FBA8E199BCCCA896888E9AF19E65878746DFC440B1122A9FD634668BA25A338CEB230C63A95DD62F9A34989CED9464667B44D31F726D477F38BEA2E2224519ADC3B5CDD1086DDB68E9A81F1905B839FBC5EF54D82AED3AD5312EFC65F9C9614179471BA6FF7BCAF6123E880DC45130429811371B01BFE89CB59F5C0584664FA6F466D6B6A75BD58A5BEE786F84A8AD5D544F48FD0E7BC838DD9FE89049B208BA72B564E03A439602BD85233B9E80DE849E7BE298DBD5B2A044074C486DF6B9497DE192B1DE55C89CBE940C1E1E7074B1B2B3CFF59BE3362D48A47EBEF23ABECA2C38733EAAE1D664C67D280E6EBAE5D41D6E077C9706AA9B8528F89DA1AF495C2B6813E8390C343B2F6E682D5F0BA4D37F565342E37DBCA26C7E0268BBFA356A045573719FB496D682CDC1E18F9487569073BBE891509E72CAABC21AD646E70ECE02F841FFA391BC9CA7A55ADC45F51DD9122F5D34A2552866B435F1081C8344C26D50AC33521BEDFAE564DA69AE91D4868F48FD0E7BC838DD9FE89049B208BA72B9FF86CA711785442F9B4263BEF02C95B2A8084AD2119E5CF545CFE7207DAFAE346A37C1585D15AAC66F458DEE29B48485AAC3A791B81D38BD2F378AA27543BC7896C120D021C3E1DC23AE2B2A4D03C5922FB5043AC110E22A0D61610BCCEE8489668E34D0E7CA2B0414FE1B32FA83CD28DC717C2EBFF9E5C87018A8BA4970D87D2D38DB7DF7E2A9E8884C4A00BA20510F7598330F8B109A2B51E90744F5FECC529050B982581D8F38363B6A5CA4E6B6F64551964BAE27FA2817AB6FE4FA5B5030A7CB5E39D0625766EF19EFDC0E95550239A1B9D254620CC1C49794A7C5C83BE8F9E58FE701D9A56E823516444D84E533F129CC8469073A2C7F71D4753A7F0880BAAD1E067AC30BA6AF9C873CA59C28134B96D8C071A8336C6B0E84B27C966F52CC551077D010B1F32E4D93FDC74274DEF3CE6D85FD7708031A6FBEC3F071C293617FD29689A31D06407B0A6F96BD67E58EECF3F62C2579EA14EE806A05F4F8FAAF8F2E298311F4C23CB77C7356038792778C28DB5C471C214EA74D71F04F41DA3B0EDD66574AE8D897B9FA70DCB13E56047D336EE0C8466E14E58EBB0F30C729129251C7BCE96BFFDADD475E9ED1497561E1F2480D8BCE431E2BF3B237BF19EDA11CD955C5CCE7F620893C39C650432A103F57525D19E1C07AD276B97F1D8705EC3C0A02FF04FF1E9E683EFD63542F1129853BDE17BB74EC87209593DF818256937DDDD0656E9AE6A492F0897C1D39E76119A4D38594A16AB3E782E7A28CC4CEFE9C2DFC8858F95A6C528BAD426356C3E2E1F793E2911CE3B079607D32657CFA9599026EBA8C119920C6927E90FEF98B7231491461078E6D4B33240546383F6E89910142664B814E4BBAE6A49D4D83FA9AC393223539B475A50DCFA05C1CA33A8EB8A05596BAD849347C0D76667FCA32839600EAF6F2725BEE2B7D6CE612D809FAF8675C13B614F6E4884F3ED2219E9817BF6D18E6CBDA25DC061FD6C108A3BADA7AD769E11E6B2C64C84C6B81373BF11F324BB0362D3A153C86B01BC7E6EA24967F448E360C322C207AD55DE75BE6CA6E592E72B84CDD4BB886701780EC67AFCF9CD5C6750F078B96AD0D5021AAB2CFB105E05F2B89630420F96352DEC138E275ADBD4A2BB5394A46E401AE7F9EDDAF7A0433B57E5FA267A2CFF4A0B415035FDF648AF81FC287FB7B0707576283823A78F2FA68AA3AA6202BA4439A774B6315B8B28E2E1DA1ADA290844D76E2E60A4D811051B42A65D87DDD4E4AFDDE42790444AB69CA29EAF2C267CE3617C18ED11AFA3412DA57935EE74C2AAB10942C74D2B01CDD38FF70D2317EEA57BC12D4D54761F02919DC3AF109CB5CA752CA349A15334855B6EC6C785AC0F31F0A92C9CF9A2671845634B666A6886D35A14BE35E3E0039A8462107B7BD1E0CC5D550B3B280C0837246C4CCA81637B9F88FDF2A19160B99524EA9F43F89727AFD866FC586B16A5D210385A675A9E9B0B504BDBB114B38911831611FBF9D7C34BD4061353330FFBD004D95C55855BD8FE01A1E0636D045ADCE13315A0DABA378CE1AB6D75B86F4160642C9FE89BE85AB3B934F514B94A9084902A1D70FF3424D2A686C0DCBE67A0A81A8748FD6397C4EFE6253C695DB2229E9DD913360D06FA2716CCF91A7433A49D6BC0A9DADC384DF239B285416BF7DAFB607C9E52BF40B69644E9596BAFFE08688A20E24ADB2403547CC4B5F16734B20A69C1A9FE9C50DA2EB02CC72E0FBBA3CB528B46AF27C4BB8D0EC34976144D0BDCE14B0BD5F677CA655CC3F4EF507A8479365E8ABB96976692CBDD0A94C80DD521B5C0D7CF84D1CC3F0FE92772E73BD6B6677042B2F0FE66F3EBF9592315003714945FF26056243CFF9C91D68D9137D20C6204700FB52A2AC8792748FF066CFA29AA664E646C1D074BFB86862297C2BF3B9B4B989A47BE6A687B8D844009B4A80417FF330C93204DC4B5CA47FCF042E1FB26DB3C8BA1339A0ECBBF580280598B2A2A52BDEDA7C916C62CD4D6E015FE771908E8B0117B19042792186C79A10B80754B6664238F097E011684F86C570130E5653DD29B061C8FC7F437B0CDD68AA321459D8FE6731B8CC39CC49B20D7AAB684EF45DDDAB0A47EAC91E95EA63C7C24BD90E0300EAE09DFA51ACB4AC08C63DC96F61D49692CBCFC8DE97B30B044556195FAF6A9D4FE4ADE085BCB2251207DE0CACF0C9AAED4A23E62DDD21CB196F271B4196F56D8BFA8BBBF1B718A495AAF96102310F5C02459BDDA76A7AB5027F717D0F3BC6AF9C1F643D5637431E01B5E3CCF44B853F1F435DA7071B2F763CFA1B3060641E0A34B29A0CC32D795558C8785D8F4AB169738114382D024E135DE4B6CE607D61634F1DE21AA3D794C8AEA29D5CF20C72D1D1C2BC059850FEDDA51E214F45B7D247AEFB2415C02A88DE93B965E845240B855EB69B3A1B932B47A784D8033588549EF6D24F6CE57086A063C645F84D0FD681FFD6113557A7BF670E67E10319C29CED990D20AE80E23B67C5E8B8FFF9AFB0DCE0956ECEBA02E44F2C443DD75BFDBB171F432A8D054A08A59B8395C005E2C25470713AB3AE09577D392407E3D16B5301913400E1D90557BFBB4147667F81A1DD8103303E338C983A15C1C57A765336862F2A1E2742924D21D8DC941A367C22110C0FABEF846CB24AC89FC5F031B8DB4AD06BB1822C50BB99395FFA484687046B3509890DEEECAA862313B74B7E2D3ABFC7E10C3A278ADD99B74B663FB5EC8AD48FC6DFB1E34ED028C74ED0A4A6A78BBD72A7D800403C34F1E204372F371813139CA5322C4E749A312D58E199BCCCA896888E9AF19E65878746DFC440B1122A9FD634668BA25A338CEB230C63A95DD62F9A34989CED9464667B444144ADF308CC1ABD82B5A7AE03C61D6DCF8EA882A316EFD4E24CE6B825FCC7F01C7D9D3BCB2D8F66CA4E3314715C61A6968F48122705D38D74BC5D97356B80B14C1E4B40E43DFAD7BE9542CC05DE4D5852F2FA8CB8C1E571DE91AEEEFA3280A16F274BFB3A60F642C13C9C87703D2FD37DB6B3A3B409ABAFB23AC21CCB98A1E381A01165B7726DCBD65E5334F3D24FE07A4AC4A86161AB026AF9934455EEF72CC2DE33B110B602A1531478FC93CE1ED0DFCE60A8116C27D8C7F2EB42806B6BAFE213BD5C42E9DF49B26D460F11B130E33005735D2F9E003CA4439462FD1C787C0E94A18CCA8D7726974031DCD1BF3BFA7176FDB5797D500F3136D46C2A045765B08C59B07795456788BEC9EE19BE389502366EA7D7F143D280EC17F182B9D94655311DEF70FD3EFD148854C528166022D36F4DFBD7E68ABFB68DA917046959A01F0A548F528BAC4FCE12CB355312E162932DFA81032D42CE1E22B5E5E2A97023920AA2531FC538CBAFD47C67E24F684C10FCB3F5F7962D27B5E82F379AC7036FB3AFC6888B88495AC59F363C344DFB0E6B054BD1BDCEC0BA17FD1432A31F24382BAED751FDE44BF9F837ABAF7065C20A0A2562B6935801317CF5BA128BEDE17FB1E484A81469B7025A5E8D201671F7D63AC4BDED5F70F271E44579AB98B11769A304D165BFE1FFB77EE5109BDC04E5D42FD96462CA08430D5D87F46112D7C5B309EA3D9522B72E221677E2B8702A64FBDE02CD242D6AF766F31FCB8B4215C0F7507B8406EF654C620201418F4FC425CEA65AD3B98543CC50380733044E77E5A15D6F2617E818B130745627EA915EB8C7C8F5A26C93339FFE9B2A8687D4A425ADA7290438C08ED681C14614F9AAC8A1CD002EE6D404A81215EC78B9ECDD513C16125BBEB8BBF0528B409FB69F9E0C2930CEBD9E5E919B1547E7D6BAB039D02CD8CE090EC7895D560DFF6C4374DEA1E873A5C608A7D72EE12EBB58A72767F1EB040046EB9A8F2049416CF5393C4B58836CE0E2F920BF599142DDBE31E513E3BA145AAB6443AAE7F95D4CF9607E753DB1CFDCA5E75C6C6874165D76BA6C498A8B9D8F5A9247CA5E6707FFCC00655358C674C00ED905953BA8C932DFC6CDA7492A53E8F257A8CBA1749111F7E24C465AF5B660A848595DEDA438E4E1C1B7AF6793428EE42A7BEAD8C78959290BC6F2A5459AF203CA33266E417EA8BD3256323C5B08671E29B41CAD8B1B34FB5616512338EE1DD932EAF7963C660625643D52A4D4527DDC5C4E2BBF59754F5D36B50E4822DFBBD8A07A9B2662BA154025EBBD12B20B3BB33EA1EE3E09998096B2F25F6960984E20A1156447FFC269B1532EC6EDDDD3E9201140313B946B9F89A176DA219D9BC14209D809A7608B0FB77BC6F78FAE1977C2561EE31E9A3AF7BBDB7C762494146C4CAE3810270C0AD5C0A5E480065460813DCDA6C2613EAFF51CEE3919C1130EF867EC21F3B9B6AB1B573F5D3C3B4B878066729BDB9171FC46E00A65FBF58961376D552248A4C08646C9C030677C59365FC4FF19F36E86656210043F91ADC6DA8A5F6CE01D0D80DE1C070A4DD4B6243F0979FA78198474A56FFCF3C6BDD196726552F23BA1324DD185CBA1947A9893D954F76C10A6D1029B996E64A57CC58A481C4B6C9AB6A8EBF4AA48061E13F55C958D004A15E63C5A48524385EF84DDC6FFD790CB01B5D77A178BBD6E34111760A428D45C405ABE15B4AE0E447255753CCBB107E6493A8633F962A2C5B9B4C6DAE7AD45983355C9A78A9A7F4552CDE3665DB9E5CF3C76E55D066982D464A705BD24C95D9AA84A2C874A7FC8BE5EFFDD9CE7D623B8D604E736ADA8E5660B00A1387DA25E59667C085DFA398CB17B542DFC61F23AD458B6A86702218291B13ABC7DC8BED82F87330530B1DFBDEF1C074C55887F804E91EBAC257C886B85847DB48F9AABEA05FEF4378E25A17F77D8C366997239DA199DFBF9F39837A1984EA1F889B6DDE5FF73A5F0CFC5CF8A5E9B2574765D526019281A3E14F80B16CBE274CB30F9013B9DF3C165BE835EB2F92167FFC60406132C2ECB5033F941418B48B613EB220360E06B6031643DA2DA3882C36A71286E1E0F2DD08B2C804F2A2D8022ED3F6814086E0CCCCAD8E4CCA5F411EC642C9D78FBCEB57CADB14D5F0BC3A873338D5A648CA6F260D2ED32C1226A2CDBB264A82C017BEE11B4968F31365A87A4990BA90E386B30FECAACA2B00F50C8D5DB2158EC8B5BB1507943DFD05F3A41EA16E9667E4F5050A6E14EA8A5DC47E6C9CD9BB579A65A7D48D05155567038C261433E88F491485736E4A8D53B87E495C643862E44515A43E2EC341F26DF4F4C1440F50068EC0A2854681F9165F2274696EE777486EC561CFDE0F721A78329EC6E2169326552F23BA1324DD185CBA1947A9893D4D74C675E45A335DDA4E1471B37E07D28B965C6C1CA049E3F62F4BA46E238673239DA199DFBF9F39837A1984EA1F889B6DDE5FF73A5F0CFC5CF8A5E9B25747654BC5B70693B5C07DE49205A27A94BD07EBF9E368104B59FDF53D647F8B9CC276E26A08697BF2C0B1C6E37942B2098F167E251B7DEF4932242A72F83579A9988CDCC2514663A54EFC9ADD51DF3F9DF0E0923741523909B73C4ED3349C1F226E8110C17E052AF344589E2C96778E5412205BB6EC6C91CB961DC0A647FA4ACFFB830F80E6003596D715BDBEF5FFEFCEA8324C34CA70C19A4E0644243955FCEDA1B7238A6AB95F9D0CA10AAB5BCE5C862CCBC2534D5B87CBB2E8D42355945521B6D798FBC7C588642E07C966C3F8AAFB080549959FE899FB1124972F7DF8E9791B0B9CE7575A4729C107AABBB5692F18A96CC3C13B22AF29DC4326CD5DA37363DD813304ED0C332E1D1E8F2934F33FBED86344F7AD4C5AC64971C12440FEF67DE92413D0B6116E842456E7C9191BDFAF2ED6053CA5DB66AC3C21C9F01F911C2A30AD75F8FD7D71996ADF5B4E8F644610B9190347BA3C5860BC420CC9B971B7BCAAADE389B6DC10AE3DC2F3D2E26AAB4A2E2AB378ED68781D5D3CE4D90FEE9898F89E811F30E5AEA9A2E0A42194177B8A1162BAD9D4A05A8084106B7336A3FD34CEC5DBCE0CC5782AC693F7454B94A335C0ED1C1BC5E6DE5E9DF17242F0D1DD4016F73C85A68D65675131BA2E044BB2DD94558FEAED3289C75BAD790BAB69DE6624F62A56C667C07E625DF7646BE7EF6B11C2824DF5B4B4D7E27664F77EF84F33A2782762DAD12C0B7FE907B21BDB728EC986C2EC3138FAA29330E8E28D3A2044AC56255F2D9A5CBD5A9AEF93686A0131CBA1B2258E5EE55C46FCFE2BC53EAE65EA3F4A3B94C587FB9888390ED7B8ABCC3C9133A8681A20EC06F5C8B22B0C1C4D6B3DF458CA2A48014255F574B60CFC1F2A55F1801A6373CF956D3F7E818090F12BD23C256C2D21CA8A61216B34223B2D5600510674E5998F58A7259B0B87BF75D54CDF63842DA7945D51335B9DA72710585504053455FE7FBFA4EE1BC9E57FAD722E4A2D1A9EC44C561E247DBE4427CE227132AAE657A71B85084AB30B8971DCAD30B12370F47E5731EEC85F502BC4BD61FFBDCF396A0B215A817FFA0E3CE73AF3E277377A7CF659D37DF583A1A72A08AA6BDD8DE7A1FE0914560F9A3637949C2E4C6789EC930A08153DBA272FE608E0A6032A0CD31D85CD4D73F1C9879C1DFD93173A23A548BABEEDBBDAC05A00CB6E14CB7B82E64E54111D72DE2D79B35FC1838D0BC3EC0AE006E555BBA3051619EF131409EFC80533ED5C74CB5919662BE9D86C43533FD280E8A619A890605D0DA1508CF724C5BE602393686A689665538498D0CE9F0F5BE836514EF13119B9E67ED12AE4CEC4C09C9ED30104961966F0A3D542E3384329116EA800FC86704D6B6AFC07A5A309A3A0614096B1FC36489B108572CD33A563919561FF724AE7BA67BB48C508EB3C1959016561C3B5ED18D8EC2651F52ACDC993BB94C8F4128FBFB261515DABFEE47D7445B7C7515A9A2B00CAB7F4D03F820921CE8DFB8478D675D74DBEA78F60EB775C6667FE544CB746435E3CAA575F8D70F956447FF322C8DD5F00A787CF2C0357FA191E9AB61249CE1290D7C13E2A3B9CDE41D6D29FE28430D42F1C3ADC894447D2A5DFA8C8FCBBECF2A0FEC02E8656EF91431033936A76B94BB33A67967419370E0D9E373473A0992992BEC881D1D0140637AE3C669F77F1D1D52715AA3EB1AEC584E0E0B26DB15750C612A4AA4DAC1D33EBEB782A32182F2D835FEBD8FEE6E1771C30D84C0C97AA479A5B0BEA8156D8C12968FE813A501762546AB42DFD3F48D45055E33AD3B45AD2D1FC78A625AD7130EAFE269FBFA6C6A3AEB878F8054225DB256C4FA06749B03028602D6125BBEB8BBF0528B409FB69F9E0C2932794233E057BEA34C6F7AAD0CC3D6DD9CB81DE96E8CACF69DA7878DD1AF5A0039905D5A6C20BFBD0BA2E3A2ABC7CE72272321A01997190ED6A0A052D9A8A96672794233E057BEA34C6F7AAD0CC3D6DD9EA793BD428F9922095A1A035B57A30662794233E057BEA34C6F7AAD0CC3D6DD997AA0EC33C3101596FB7945FF326BB6AF48FD0E7BC838DD9FE89049B208BA72BD06169398DB3A1051090D92E3789A7D3F2211DB2A6FDE924EB21420051BB21592794233E057BEA34C6F7AAD0CC3D6DD92DC72112848C19E45EFA865AADC81CDAD61B71A90A3D59EF287219B5E3D8AF2070840F4C21E9A7DF3A7F14692B9CFAB917EB9A11FC8B162F5EBCF26B6D7DA277AECEA545801B4F78D4A41C196D7EC74917658D4A3E089CECCD5129448A0DCA6CA0F758D72C5876E9A2F688D66FBF3BCF16B67F4C31ED6D028A77D5066B619AE661BF7BAE0AE0C922089595126B64A59DF81034D9E8EFD073A161B19283F79BDEB75E6D4B64D85DA1FC26DC9FE77CC389A13F6A6492CD4AD9994293A90AF4DB2C1578AB23A206C6142CE70C94EE27A25315D66A63068A06291DBFAE1DDB8084C3F8ACA414F1607DD5B6BEF8180C36B289468AD94A65A0521CF19548F954D3F6F20823699168EC1AA88DD581EF9D0A984D988590566E2BCF10811CFC77F44B57E858FB84B3117A37C621566FAEA88B0E19BE96E021139277EC792438913E096B1B1F411C52740527C6C02F68ECE03542DE5FEC6499BC965BDE0AF73B8C3DD1DE8CB6143E0C48F21DD239CB0E2DCB8D2050A47559D857E4DBE3A0986CC7692B15260376139611B3F438C28566817F354CCA54C6EB0439BD6513DF60CB2F5DE2A8887CD1147D1C04B9A9B92D0DB48CB809FE8984BFC663DF1458DEF1957E53A226F9C38816CA8CBE2A2A3CF0322F71DD300284408CBF780E667C32C3DC85C358482F5D7B301E4A0C281F0851A001D9A981853D325BBA78C2E1CE1FE4CD0E4CE1BBA0882008292AC1EE6F49AB2384D934DAD3A58A775D36035DA3FCBE68574C2AF0C18A3CC5F67E2C0B67D9629B1110F6B791E6A7BC3CACBB9AFB28E86246D7E2255025A3606984B6EED2595C6897A9C734587B2445D3CC463986727AC9525AFD899B9C49B70620E0CF8B461B36FEACB97083B190F35128B00CABB57B3D6F6498A323175533A7FC1643FE4DC70DDB704BC5DB861F7B8B7C7007DBCAE78DAA4EBA54760A606954380AF93513D3047C83852623A0ECCFD8F3D96404360146D87BAE04EEF2554005493086A63C78F2DE57F1F1AE99881D987FE050564169C33C483C0B5987DF2E87CFE12915F2C61F1A0F65F06E16B67F4C31ED6D028A77D5066B619AE661BF7BAE0AE0C922089595126B64A59DA28E6D8F1EC55BD717A0955F4E88BE4F73A0E832ED656F55688252AE61F17DCA488FCA38BE1D84DB6DE3109144689A797EB247DA801BE5B4C06609D78D5DA5732B002AC7F103D9234BC3B68C900D985AFF3FD03B937ABE4721E110F7DAD7DC89813E8390C343B2F6E682D5F0BA4D37F526552F23BA1324DD185CBA1947A9893D6FBE83147927D29A51AC35BFE60CE018642D578823F5C3810168A8A32D0F1C512794233E057BEA34C6F7AAD0CC3D6DD9EBF0C03F40688A88E56947935A79713784173AD5E2CBED757C371AE0A213EC0AD8D9FE1B0EB218ED75F4F8F458E699A04048AAD306213A5775867DE1B1624DAE6D8D96A5C1683CCADED7110BE940DCF6882BC69B7C9AA62BC2885EBB5DAC63130D7A284E1C7A5956611566E8C36C768A0CC7995DB89A8FE814AA2D1D6557E751081AFD3D3EDE17839807267BBC50FC6001E2F5BF94837D4ACD7E9D619C4EB3D598966CF407F44A233A47C491671F585BFF744448116CC8D28149F6860A2343FB1751C9AD2DF9CCDB7C25B4650C2842A5EABB4E83E5F651CC9CB5718E68CDCDD1281C868F092136A1B352F5338F98B0DF19557AC9174512C73489667094EB1BCEB03ACDDC7AC6A00FFADC62D50F4D078BBC072AF2218EB9447632EDB715574CD30F88EF6ABE760E9D4EE66F163525653003699E9E9584C36F7E3EAAEEF12EF862F0E5C3A2552F398B84356BA149AB679BF81D64B5678DF263952207D76A7C440A813E8390C343B2F6E682D5F0BA4D37F5745F606B50CA9B4127028913A71A5D7F327CDBFFB614AE2933CD76176C6CF1B740D4725DF14B57C77A034D9B6E16E8FF65FC4FF19F36E86656210043F91ADC6D47E6A279963998E448CE647307AF6A53054456B75FBA1BE94EF09197DCC2A13CCEE86722B46704B1EBD8D7B5C67BDFB8684CC14A80B9B3425D33484F540790056E2020022394E2BCF082A091C13E4706C2FAA0BC437A0CE63BF5A2D92EED172D198FD913298DF56EB179F7E92C416E7265FC4FF19F36E86656210043F91ADC6DBFCF4DAD81C2B82614435D6A884FB660E05FC21D26E3C3AB39C289FD8827B843D63BF2AE56BCC2208170F2C1D0C00EC4052999ABB9D8FD9772717A3BAB2DAF65E05FC21D26E3C3AB39C289FD8827B8431DB199CE19A582B021BC4F323AB78719F8B069007106B5291F47AEEE001215386A8DD97C44800E434434897FAFF87EF17F9115D7C4CFA2DE262A281F7453841341CDAC90B33D0F8412B88469730FAC846E5F7A2509C2AFDA19060319C0073ED6AB8E0944E0C3B6B50BCFD29CA22823A8F66895E98D97E513EBBF2E96CB2D91269F33B18B56E64B541D10ABC2EFF114922B002AC7F103D9234BC3B68C900D985A51A0CD36F183C4DE446FB974F2907D1638538E2F04B66C7D90FA9C43D108ED4A9BD9B9A3252072B9181CE06D76D5DBD5EB4A8FB6DAAA743792E13839926658B1FE7864098C4CABE4187281C1893AAAA757F94EF31CDBF211846A0196A8090A438A2723ABB515EC9674685B7BEB06F85121E3C7742EEDC1351EFE12AAE91990D3CE5BFA3543A1996564A2BECA0AFB5A4665FC4FF19F36E86656210043F91ADC6D7908D22D397614E4991550ABD1B6AF9521B473DC8115D6E55486968E6196D4C4471397DCB6DA52CDF4EC9E15FA44C5A1409544ADDE4BA63C03C122109625579CC189DE4B2A5D763B9977C3ECC12D7FDC6F57C7784D97203D7F73B52A22AF6F99A7CF784236E494A717DF3C7D14F5C7B7A8729E281266B1C8D69DB5411C6233C0A758638600B0343814F00891AED6255A0F46F99F74A2CAADF510DFD363CA02DA123BE6CDB8480997FA41045D9FA8C6E465FC4FF19F36E86656210043F91ADC6D66B75740F68FBDEB0CD9E9236833B8782B002AC7F103D9234BC3B68C900D985ADE2E4D64D13016011372B93BAB0987B2EF4B1126F48B3935E87ABEB1F9A77F1967D93806866E9D1B04E7002461E4F01A19E5761CCB5578C5581CCB27C903C195F48FD0E7BC838DD9FE89049B208BA72BA8A0335F3EA8FE1965E458A8C25B96A28AF4C69E1ECCAD33430EF88FF87E181FF5CAC38C5D91D209925E8CBAEA361A71FF36F3E2C16F068781CF971EC777676044A66602633A3720F9731F64340177A98271340E7FB43734CD6D709DD34303C3038EF2178E27B4126671ADE212850D6E35B7BC274AD2575C3CE36331E958E0E0BD46097CF3D70483E462AF0E4EC01692CA1942E97AF31F49DB921CCC680CE3D8A90CECC2B79ECB257CB47A43D914BD679D15784FFD84835CF142FBCDBF7B7CF73FF9E9F0B73DE0FAB4105E2D1B989FB161CE359BF3742731C71D25DA3E6C80CDAA29C79C817D8F0848A610F0AAE1DA3F21C984EC0A806A47820BA205777B48908F56CD1AD5EB66BFE27BD16CEFEC3D4235DD5C60ACB9FAD2FCF8799B0C6A87FDCB4DD3C9383980CBAF77E041E44C6AC7F1762859DBBF684F1019A82C43EE5D5EC86FA317A9CC92D4D1DFE4FE7F8CD7CD2B002AC7F103D9234BC3B68C900D985A92016F71A4F4F81258AAE1B4198BA0B117FFF99CD4B37FD0305379B4A5937F34EFE12C7FEB90727C4EA0507C8E6AF8652B002AC7F103D9234BC3B68C900D985A63915245910C0E9036F52B7425099240DB736881146C46721F44D481CC53418B4ADBFE8ACAA62DBA54AB8271BC12607B2A5178E46085547D51717BB24A51E1A5C42B6E4165E9F29BFFEC35CFD78B6FF69058176F74BDBED36D2730BCBED196C9CBBFE7F18B4088A6C3AA3F981B2CC2E1BDCCB835ADF0426BF23F19853694CFC8813E8390C343B2F6E682D5F0BA4D37F58C814517B3182D1379F68F44D58724EF0253D1A346A541838C442A4705061F75EE65F2F935E30228D1D4ED9CE0E6237597379940CE76789E9B7452A6A016F5B1712E0C0B10A646C77002452F1B202FF9CC6BF6C0187736DDCDDA2058C7BF57C9E1415AAD33964CAF24166F18DC0E4970E5964C3EFA4B3DFB5101A4C3DBD828EF0BD587428908794685BD38B8D1BA54CCF8B069007106B5291F47AEEE001215386A8DD97C44800E434434897FAFF87EF1E78FE8AC3AFF6BF5142F0E73519486A473030FA1BE2E600EB672D12FB3DA46F3CC6BF6C0187736DDCDDA2058C7BF57C90701AC07F7331BBAF5BBCF7B3E9D9A94430A9C8250AB10D0F10C40183F9FD12600E68E49035E328F930A0B1BF2B3F7DBFDB8EC3E5B489390E8A9D844E2FA3FCE34B96D8C071A8336C6B0E84B27C966F57C17FE74CAA1B58CC2B09074505AE9900F88EF6ABE760E9D4EE66F16352565301EE7D098CB6A1A9B56414BD69EBF0E640F5CE4E6E66B88ABB8F19DA021E682F99E025E563A658D0AA71415B01D56C56B2794233E057BEA34C6F7AAD0CC3D6DD94F0ABD8D6B7BE77A9DA0DC326E848FBADA167D95BE228E3771D46AFDCA4B78AC40D4725DF14B57C77A034D9B6E16E8FF2794233E057BEA34C6F7AAD0CC3D6DD940802DFD61C8B5D7FB6D92791153877F9D0D0C94330C04F4D47C0E09AD35AFE6C1990FF8F3B0703ED547A4AA985B1BB47800217EC6545FA2974D031054849B7795A628C9207AF0FB8ADF1D7559B03C4D9FEDF3026C2EA963C3720D7169097FAF8BC8DA517126CE28FC3A17310E4992DB7189F2F9B6321CAFD1DABBA80C5D487F2794233E057BEA34C6F7AAD0CC3D6DD933B7672A26716B96CB4F24B3122837119D9D028B6E06A6AF6231BEE8D1986CD5801098D1E49C00FDE0CA5AD30DF80B10730704B3B248D00CA86AF665CD1876C714AA496288D1C33B429A9A43675F591C2B002AC7F103D9234BC3B68C900D985A4062C28825FB702549F43BAF71DEDFACECD527A492C9871DC8E5DB1AC0AE46FCB90681E2FAF82C041F6846E0AEDA998F19E5761CCB5578C5581CCB27C903C195F48FD0E7BC838DD9FE89049B208BA72BDF13548F9B82DBDD4169E1EDFE483B7FC3BDD695B61FA3323636BFAEC835F7EE98A2E41DAAF2235F22294A271F37E37F273E386B5171DD2B04ECCB9DDF6F72389C1104F749A15295C2299CDC6671F31037A1E16A9D32EB00FB887B5B6099345287D6DD612E60F6B3F613969176CE87D547C8BA09B4D9F146F36A378B3F6FD7D952D92C815E46BC5E4D74E412C198B96ADCC2514663A54EFC9ADD51DF3F9DF0E0EC11597A19874360E416E30951137EA6B378ED68781D5D3CE4D90FEE9898F89EE64F32D3AD2132BAF7F8E616D14329B8EA373C7DC6ED22696F2544481147AFC2ED4219BEB9FEDF2FADB51B6DC48C70974F90CF931CA38C2932355E10B8CECC521ABE11F61BDD217CB033FDDE1858E0390DD781A59C0B8DBAC3DEC630A441C94D8EE59A2925C1FDA26EA938A2A1673E7325482938766C0298D7501EA5005832557EE5E0DDB5D63C43596BE95E40C62BF48AA5F4724214B25496F27BC1370DC01C2D0CD4CE9DFB4C36429BF4D16929F03ADDA98DB8499B79C7566E37191B9DD9CD08CC4036FCC0DC5DCD50B8B846224378DEF1EFF5729A7A2FEE84BB95795FC5BC2D0445A820F5E07442AAA6C531D58F412DB84F7057D554843D635327C0F4CFF1516A98E3284D18BAA1CD1B2CE384A7FEB17CAA17D6DD8F32432B3FB21BA66493E3069B15565F1C8911458BFA14AF16BD3E6CC8B986B60DE53E0826BF219109128E5D289F4794764C293B09C108E13517F76816D5C46B574CB36D789CB496688993150871F9F5114CA6CC77AE8E9634C1237C928902D6D029B84AFDF3E9E2CFB61CAA5A685E73BF1A0D51483C339F6E745142818B067761E74CDA7106F40BF22194B8AC0FF2EE6D0CCC819F6219C0420E6723AD0C033523150D0F8B3BD92E4C6C88D7D4C694160E551CCD828F3CD24CE0FCEF93E282DD8DA217ABC9B766A61F6E0752ACEEE0F23CA8304452B51CAE43ED7178714E3DB434950CF9324AEDF8668C3EE876A15E2B4C2EE89148FBC7148F2AC49A4B57CFCD3B965DD7A0CFAC70CAD5603DDF3F6DC77C41979BCCB0BF0C56942FA29F14530B41DE02568728C4048D7FB996FB41A167ED5100A3B19A415518F70F2642F42C60BEC6482E504B0B06752B1A334A74D1E477852FC9C8F9E7833B4AFBF00EBE4379B32E5C0CD3D6AE8F58B9EB831EDAF569550EAF1A262DDB4A081BE8026E49CD4369DCA5C2155B2A1FFA5AD276B650912C5F2CB48B43A8E7FC44EDA1D7F3CF8A46FC9ABAF51D2A7E0FD0FA06818919FF19BEC8E817B254106AB4E31D37BC32CB80EF3D1E561098EC818C9901C00117BFE8AFEFDA13C5F278F8DBB352C5229F49DFE74E3541104CB871DC6654D08DC555F67DE1D6A5661E0CF35056CE194FF20979AA1505E30503840152EF8DDAFB5B4DC0332DC861064750FB0D880CDF83229CE0E032C492F6BC4A80FBA50E6B4940A878C661E1BC208CA3B0C511AEAF66EF7D739A404BFF334AF77F75B4B9F3E91FEF163892EF02251B4762AAD33C2260F046F5E3CA8ADA19F14188D46BD5630C8B58DA8F0C2AFFA55921C20592B31AD13EB9327E8E04468B08A98643F6A33D29EE6626799CA6BBE34219851F651D9707561F9FA958A944CABC1927615D13EA6FFFBAAFAED344394EC538E3975C5018DAFC46811B95B21C569FFE56BE750507D580ACB9088994B49AEB373C6BCDA58BDCEFF1FEC72DFDA01B9580503929B4B9DD5EDAF4152CC784B3E765C620542B48236F9F89E90FFF6C571639617D5E860B6B9BE6C2279959223FFCA694E261107DA1604430E863754F0493985D5F06D9F6416C9BC25C08095979207D62293CE872A9D127571ABA6E3D89A32B74276C02B51676EE052277B5352E006C283BE815299A413F53C4A676AAD6EC22EE8772D957F5FB9E6BDB70FA17561D4E29ECAA3822C83BD683C3BE7A1B4FCF397D7B8404E1C9198F67DBCAF6E561AA0673A84640D2540C6964E302E4BB20BD904655382D3463F6991E6E91ED2AD06CBC8CE9B553AA622860E6A22733105762BBE62E1E819F8B884E40ED4AAB4E6670544449B69BFA0F88AEA2F66B45C0258744362802493945B6056C92A9817A4AC4DCFAA239259247E9A1DBA88BC7208E82A2803DF43BC30E5A4620B15FD27508E0CD0D63F97C2C11EB57C4C4950C58D01EF916C6ECC9E17E429E63DC5F40053A20394CC905A7004B2397C90190A138E014A9B6187AEF4981938103E1EF65FBBD2E2A06CBC090C3029EED358878734BD83B9D0252DA2E942C3FABB7668599FD9D6243A5117AEF47A7DCFD0A2DD8840C2DF0D3927AD0D9D8D281912322653B8DB39A89A59011743D90285D13B42C260DFAFF8AEF7CD44F1EAE3B8E4390778FBF6D0AF6BB4A189BF012E57CFF36628A7CA9B827F0CA5287F6E403CB97BB4FA3F5AF13FEF2923CC4A798ECE38B3D142B855962E30A24E449A6362E5285995FC53DB3373187845462E5F33701CEFD119B8DD9EA45AD6AA04F2CCAF2BB676CCD7FFFEA24AACDD85C4E5DECC6BB87C3ADA386DDFDABD448A5AA64C632031737E670B6C50E3738C94F4BC88DA5C24FB76746225785F0BBB2FF3A1ED0DB6C0F26A48FD8DBCDC98368AD40C4A6A8E1D9B1EB604F91A978A445A54321E3465155FCFB1FA11A338C8D8CDD45B05D502C97D1F3DA57BF7BC0A9C78836D3A2A16F240074C8E24FC97E6E3BDC41A653CF2C5392F9D32DF4811A101226A4099C83B81F3170513556227B740B67D7C968F6FC592F0C86D7DD7866770AD8D013E4F9697C8F2B23DD30736B9C2DED6AFCFF8E6F6C1A9D5EFA37F4CD0F579F639866167C6ADEA66DC7A96C45A2D1D9EABBD434F651CE10602145A69195E4B54900A9849E471DC18826C39E003D4A9B2B8D40C0AF612B456E08E6D8E3C74B2ECB3436987F15571CAC565F4693EE198A75A77C7D846B8932C7832EF7F2D0239A4D1F7C7B60B44E1C061945BA68DC383081BBF36F9BEF724C53BF4AC507E12DE65A846E6FFB2140A8CF466DC76D58E4CD6AA6D9B93DCAD694E9274922FF2DD9E62B77969428001A9BED6D677FB1EAD28947630B64D6D9C4321A649757AF2E2DE6AF0E09EC75626D296729EC1F2961D09A909605AF1CAF2F55DE6D03F3670253557B42ED69509551C85F135DE8432B22263ACA1259B664F567EECDC932C6F51CB1E8E3BB9E68C08942E19A5AE9AFC9125519805CD738B59143206973B961724BD34D255FBB1689CEB5BF6F44039C303087B4605BAA964D635A21395944834FCA41EC498B390B50544F026DD4796FF7DC555688835073D9085FC01458858073263369D88CABA7713F48AF22D8856CE1E61B11315F4B7D737D266314D5C2B5D898EF83D489D214D322A277C0A9DB24B816D63D5E31E442CD9BC9C83668050637A3C73589A648E18FF4DFB8FC25C34C89E84A954CBBB69B8C024667DD52B0099173C709AB06627D3DF4121D1921A6F8ADD18661BB61AA226DFCC4B87E3D911A74935D22F25CDB187E1A468CE47DF5CB69981377E435B10C49A9CBD633CA80776236446CFA85D88E2F2ADBA8587C0485C314F59EA948C593A05B8057B9EABD71902F4B2CC998DC884C184CE5BEFBA413077CA2D9C5D1D0FC11EDE191466C689CD0A100050BB2C80FF2817ACE11A8990695F563EDD6221DD009D5998E9A87D88D940EB395DF50C4F2E16282C92D21EEF68E3234D2AFD1AAC748A258A60713DE15BCF30E15B2708A333EEF208BE1B7A612F6FFB14F1DCB06DA7A241936755E6437AA9621C330497A93953057DDEA63A47CC2FAC63AB86979CA17237DD43B95603B0398D22D3091B9EC9AEADE51E05D8686AADFC776B9F5A1E80010334D91EA21DE1CD7A7B9A3FBBEC3EB96B8CA1EB4B3B20F6F51F9390514FED5583FAF94AA03F76A212FB3B0467F279D86C9C17F1526193533390BFAD78819A5F2167CAC410907AC344BD4EE25C45E56154127D71607A7D8B2452EAC67F51095DF9A6DAFB17F2C58D5227F9E0B3619A7131060E47BE767E65A5340E2F1928666039F404454B8EFBE84E313F20971B32278EBD7BB48ECAAFCCDF49EFB1DB2D4365AAB99535DBE163508C6D653FC056A650D0740F030B8B76F6048D12C64A96365E1D9E5C98BC5BE28CE5C4CF91985F03184FDFAFB0005828999717415946B9681F68540F8C80241B6DA7B83FDC2946BFB89446D3DD45BF098EC6E0AA52F691D3F78554D75006A5EFD8A0275C006B7C6EF56FCCB074359FC9E48232780252633BA77F0B8B244BB97A163ECE671F3850E40F332CABD80468AF983EC099D20F0639E7BB50073C3CC2144A7A64C57EDE6680DE6987C9D86ADA012EBFDB8C6E6A162E5AB1FE3599F25E378B97BEB161FE3D217897223C29FF4636E963FC06CB48AC3C98B4D907E5F08936C088AD2D7C0166A6C058D6F1DE54BD2F897E8AE40EA7C9415F69DD693CC1DAA06BB6CEBA729F39706841A0912E141935B5F1AB3A19C8D0826FFB8A3DD8AC2B661E0727B76112390546E1B8FB62EF415C5CCB7FAF7E811F45FA85279D119807C8F11E1123460E559CAD8BAF960708F3020517764470E6AC7E18F0B252449D686ADB3AABA740B429D66C6A8D1DDFBAAE73CE7FC8D57C2D7402EA598DD5457C2FE511AC0C555BE30552CDC5BDBF53A6D5916CFA616317FDAF9CBE16FFB95124522C7269C3375889FD39690866CEE328AD19CACDBFB24A8562657D6411941121CC38651B44BB97734D355ACD40D2AE21A2E6E30E174625189BA7CE12D749F8015DF2BC510B581E7520CBB075F5F988107DA8803AEB603AA3FB79FC45B4AF1DD86E44261656F71FF24B85F249C77C6C968FD156759492579EDF02E2854B3ACB618F8BB07519BDAA92606763D256C1870E4705DEC77C941C595C914E85503CB3B797CF11AA49E5A372CBFF215DA73592F1ACDBEB181CE64AEDE16A5EE52F43147E78F3B01358863ED432FF269BD1DF32D641C5F1604E41169618215337A5CCE6C0877551286DB7342B06F2A3E28207F956B0DAA98EB58A3567C784D5A5E37EDEFFB7939826D60B7AB0BE36759A87666B01362D5AF13C56057D952F482050343AE5632C35ACF19E6840598414E4F2CE2AD955BD501FEA27D7ED25C52CBD854B35FE4B64AFD59CE40927D7282E9156F4AEBA712FF06C82D14CA118F474FD9391E26AED18C31C00A8826F4530F9431BEC696AF8A922E202AB594178C6AF2EB5D7C7E6D58530A33B58D7EAF823565FCAD683E88BF7CB47F8A1AE8D4E1860F804A372153D34FBB46004AD202D1BAFF7CFCE13E63100B3587C7AEA221939C2ABA6EE04E3C46B9575594F6D98E1D678CBB57FB35795293B2E1FC5710F8E038A496A0F59F760C62D741AE6FCA8138C4D0F8FA68CFC403BCAE0C9D3824E14913EC725560CA9B6F8FD850A0E2ED056CB54244952E535ED71B6FD0C89C0772054BF8F0EDE3E3B0FD9B2B24C829E8224222AB1FA19A44A8B18FB88F7D3289B3233A4CA2F2E2446AE9E1BAF290F3D48CFD8D7419070C93F865CBD1A2EE452F9EC9DC0FD324A5B40E21BAE836CBE2E83BBA5F00C89B3CDDAD0C88217DC4683A18A4C0475DB47204C70C00C8F1D4A0F59D294939F4A662B38D04098E94A3947FEDC7A9AFEA01B11C69BA18A3F5A7B7CB3D9C4677E37F4E4F856E489C0A45E5C231FD853AA16990A78ECA4AD9212A6277BFD02379B363540419AC3F88CC7869087098AAA6F99C1D9509B5BA305997DD91F4AB86B69E0A71A9CCD94F02F6993A52BDE6D26001092B7BEC4D16DB0F84A82902B3CF098137DA243A9EB8F72E03D919DFBD37702C25996EAB844AF28E66EF88E14894A0EE952FB277A260F3456D3C80696CD557C2AB51DF28769F8D833E40D3BA541B26FE020EBC9A1D052C44DF9DB9AA55FD3318CBFE4BFF954E1015EFE3120996247E777FD39617A6CF33B23888088FB2864E259B6F98DB25682C0016D40D482CEA63D87DA7F319DCF25DA2D5FF67F5836A58E54F82F4B34B56F9F35DB0E8E133C692725877A28151B18F660638109FE4C15A62057BEFBD2C8A0CEACF5D831A95C695CDAAF1283E163C183472EDBAF4702A25992280C77C8CB48D36F13ABB6E084847FFA771FD32EE0F283789DB47D4333B01A74E15B8BE99D9F10373A61E60473E80179C98DB72F1DB0654010F04028385E2B9E6F3A9519EE09293555E2A828038209993B0FB4286DA1A9B3F7E1196C2F4AF36183E55B8FC2ADC1C5E3E3F9CCA93F9D7BE16EBE7ED8AB66773F9433C4B988CAA8A5DDCCAFCE8640607E205DFD16A351E724CB46F7359CB5454D64329608D9244B87D149E286A6A50FF9113F2193E6847B06FDDA5F9EF3164C3A26D5E9F140499B482106BB534E630FB0AF6A6BC1AE948FFA182E4F1502E459342695DD07E8B6D1C96262FFD476891A9C3E8579E2E60074EDEDFA17E73ABBF5F61D55CAC55C4BF07EDF51345096F0CB30D0686F6C7CA7F64FC87486B49352D16ADEE836BE294E039451393A16DDD0222641AD2C3F82F86889E57FC7E8886C3757C4103CA0982359B488024E68ABFD26BC089BF47A8812F1554519156F7572A872E7E1045AE653ADB48907FE6116D9E255FD09AECBC760E6F728C18BB7E7AAA8EF251053D76DB224034A6440E90138938784AE779FDCAF685AB1113024A3A8B8204B95F99216BB7C78F8CB4BD9B0333FA478F65C5948F8D8082AC678AEEE75F801B1DDF4FC9C2DF762C7B45B118B50632CF119B0E582CA91D7163C75EAC0FC9E9B4145A1E1861A74FC787FB39C0874B95C53FEF051B6DF6799980B183EEAC22D6B62FB768D76F9A56F5FF9D309E5889F2B1AC28AC6D084A4F46A1C42C5B3C62A4C5F40BB036FFFB04CF4E8B0CEBE465992863D1FF8937758097FA8406489E672ACE7E6BFD6D9426828522413AE4B8C65F566FAA3E8A8CD1449156EE432AC47D0B55F2B4C215F9A9548AE00DBCA6F0048337680EB59E556CF13948B4C7CF1A9B97C6D2E9FABAD35A8BD94E2E77D1FAD89DFB13513749F22B3B9CC864D105563AF31E4EA757C6281E168D46C4D19700D1574663044D7F65B9A356714CB5E2E604919D7180F88CC3F8D0C9A70BE7BCA90EF5783847A390DD98A3A856C1275A7D5B9B6A2D1167D8C3C07A805D421422B72ECE223F08C2701B0BC8FE1C0646697A238BC2B597D866432BD938DD171D7FE6F14836D8694515988C0E198710FE6DB27E705A1E72B80B37C49AB460D3E3400AED944AE9901AF9712C2D569D0A25F735DB16F82DABF694E687E308C4CFD12275737909E3951B778C4742AFD7CE34C1BE26CFF7E95708B4B991FDDB3930117F7904156C00034BCA26221F6CB1BD74F19A91748BCA40519A3211139015CCCCC9C3E8E9565F39549891E10651A5479CBE50CD951CE9F1573966CE124F24E7C07430B769200C2C807880069C1A4085C7DB8E3DAF19BB569CCBAB32627A52C17EDF0161716694A5A93AD1281D40D201A2ACC9361342A11225C3CB2C3CB5DB630FF6B421D468132729DA09E4DC9EBE13F2C863EF3C1FC5C29C327D7C0042DBCB538F0C089C1CDC456A4838CF09EA8A5F5389F800E5D069D850F0A2EB749A64FDA5B4FBC42FC78D3F797E5278CA8F45F01A0F26B288EDB0EE762CF106B9DC73E918D5DCA3449D3B6F38002B4C6C47694C730B46FA3B333EBE0F5BF65648F2F9FBB1A92A5EAB841A8433044B920775FE04B1BFB9C86B79CE83D577CF1A6BF56F84ECDE18DC8E4A2B1C237DCE35E3CC811DF853D43B094B75FEC3D81977AF6D140B9F972A3B757D9B7A8A31F980C0B80042C14B44F44472AEE9C84CE8AF0AE38498E86219058757E7626FA10C0382AE595ED91C317AF783A72FFBD111B74887D8D011493ACA6A079FCF87699F6AB9E1C5FF74AD405128A206AB963A34E0FBAE5E684D1F9ABBAE310781365830A6FD6E17FA57DF6B8CAB9FD8693D6C9E77FB59CF470BA9329C8670DDD61135A1EF9FC905E6580EF056D676B40D1F56D2AB470F5C8ECEFA787F11955DC70102F46CA1E0094A3F8B30C4EB0DB9375108E6A30A3818E9FFE1FF1BC3B4F667DDAF3B14C12FEF09CF11A1B81C5758D2B39B33FAF356C44D8268FE6B5E852D433B458EC61B21C465B71B6FB4E735AD4674923A643EED49B7D722AF0572CB790EAA246381AA7361C58DAC7CFD02F73D9DD029192D5A7A1DD5F92591550B73EF6E510AB8BB42BEFD43A572A7F8F79F85B6E62CA640FD9AECF6FBFF71D067FD86C0BADCA230993B44F59D877929E7F686A37BA49CC8540E9B26BF97DCF5DC7A6704F373A050606C22201CDAFC77A2A9E5AE3323626EEC573D01CC3E40AAC327B9FBFD50E3B89192E0A08D18CFF0423B524FFA6BABD23999E35786ECB8D2FBD511A94455905CCACF6CA3D389B74007AB9920146636401439F49FF9CD81A5374286F6880B4A766E45B744247A5C51E7056B9ABC20EF09EB296A9C379D518DD54A0F95B5198119179726AE85FDEE9A475E828EE4878E9545A159C940FAE33BD99617C85DC14E68368E83DF39A0BAB552591C2CE27BC597EF7EE6E023343D8A80FF2ADB7A13E18CF0DDAB40FFBB6B696DBEF1D4F823037BD19D25FD79C5B84B002E13039280331141187D2D271DED365B0E4BC0D2361F73888A884A35F0958B153C76B93C87CE5256C3E85561816A17280B988425C0FE135036BA2C4A35D6451F7CFF7FE1AC25D88A55E9395A65658A894169BD32808E4FD57F3FEFA7E08363EB2857A1EA6A2442B2AB1D893396FF65D26FFF940C7D90B494B215431643AF450B9448B4364CAFB614C757BCB72A54F7A79BA31C8C655423CC6C2E006C283BE815299A413F53C4A676AA372868F901FA131972345B3ADB3A1C2C7D688237B1BF7AE44FD1C9698B443EC966B9548BE4148E5BD9A8A184706796BAAD4606C3FE073B942792979FE56AD724DF757EDABEC83B4AA2D0CF56B8D90691D09DD564AB2D722C209D53D70A307065A70C4B6CAB585CB57C76D3441D5D8E6B83710C79B20EA2C611554A3A30C51CEBEF9E3BFC1187D67D6ADACADB00F86161DE19BD57B4003D16921084B3717CC26281F417B0EFCCF8D2BD6EF69C64255F20B80119DAC37E1A544DC33D9F02E38847F696630DBC58911B95B1587D04B96929C2701CB8D68660C0BEE4F7536343EE9F4629A174138B40F43B0AE32158D38BA38D553D4D54645D0E5462E6168B566A65714120CCFA1FB36157C835E6D3ACF439BFED61291DDCC8638BCA6BB430E71BB798272B0FE23EC88CD2A2AF395BC5093199627ECE3A572F77641A99F55DEA51C2ABEF0E129A32AD2B2F388AD69336691D3C5473291A98138A439750BC8E62C225E110535868F99257AFCAB5928F58ECD43C4273EA74D7A0D4944864B95289A492561180F8D7D68AF27295E4F0C35A183E24288A81C9122C3D73D0B2A2FCECA82B5AC282D3267FB0C36C9506392018EC20655C1149216CC6AD3E987769F3070E069CFDAA16C0D7D3465A8418D9047E520D38B81BDBAF445CA73DCBC84E98F719F31CBCC613C73FCD52D29AB9ECAC17EF2CFDCD38E9047428D18D1EBA4886D4222C61B605CB8AF07E0D1143FE0C03A868622F57CDDEF37B57AF9D90BBA10B2A2DE228522A4BA97F0E13B43979BFD1DFFC12BBFC65B8B19C3F35DC29BC40BBBC31C00FF8D21BEE7BEBC536AEF6CD39C7D037F178376940811E87DCAA828D560F79A72D88991373AF472B2A8C04168E08B5F7F6CFAEAB3069696E7DB7BC79E3A6F6E338F06D9680A6E3BA7EC00D32DE544CB33E400CF7DA2766DB2FCF3F7896BC4B00759C5516B0D39B422AB9C747A1AD1096FC79DB4E18547E4FB7E2F18AF4D29A58759E428952075384068FD6FB0A8FD1D0F07B16D9D41F3BB38A752091B80A2BFF4B995BEA998AF707557FCC93373F24F7F83BBD1B19055BC3763BA8D9F8902DD78D7A5EB599916EF59A4519C5A4006CC5F3E964004657B56915B4B3945D39582746B3FDB791B3BB5E935EF576BEA26B53393539331E113A6E8D32F94D96E1C2DF8EA74BB9A3BDD014AB45B2A7F86BFC0E91299A55BCC9CC0344B9D681C7442C329246D62A0993E423E509D372034C7844F6A42ADB873C51E6BFB28DB6236C7C9F7902DEC6BB99B3B787B563B47425A4228C694449F977992363CD7B068D9C2BCF3D9A29E628DE28A0EBC860A01341133D6DC34334BEAA1ECAB05304F7D9D935BA0AFBFCAA4D3009DA32172D6EE59EC4F1E2297CFD26253ABC8F877FDB5EA30CEB3FF791B763C0529C46B5B485453AC720E979326A456A2175DF15BA5CF64457069BB76D90F402A72E145D12C8D1BB84053457F6652D7DE062EB7F3D459E5485CF4A224A7B7A41083A0B7D875E2F8293270FAC6928816BE66F35185E82CDCAFF589BD7741E5511567815DF5294227E56D5949906D5476C73CD9183E9A0AC0357DE0D27DC7710581A13E99C0B07D9D1148AD3519B0966E134D353441A473C48C8A9451D90B5473977F15FFA6765CAC50E7CBF362875E475D769F71FF283071512581173D9936DD1396F13CC45DB9B685ED5917C58628EE2D302776C24D69170FAD3960812ADF5CE1BE587EC3B6DC047634D3421A66967E51DD34A48D418303E7AC90219FD714C746121EBE25D5F23107B2BC7456D11DD3BA5276E715125FFC6E41CA0CE23437AFEBE8CE8153F9269DE230A75FD0516FEFC4D306D5AC51320D216AF2214A6F28E7353BC13BDD2905BD0C66DB4C6D8F82D2DCCAB70ACFED1AC4549C4014F90EBDEF7DF8212A18AA36BA78FA19E34382021A6D3751BF83850FD7B5F2635681501E21449F38530BA3239A3703261B08A7DA8F6CCF4CC4CA2822688E5C1082A12F641292835FDB29B28CD7EEE7550E7F6081B469729183FB5563A7DF9E012FFBD200EB8EAA663B13F226AB1D9435A7EA62F3DCA88C7E42FC0BBF8BA55EB8BDB5166644D11973D7C194BC6870870FC83DB1FD1990FDA825E5FAE675964A8F081618050188DE359B195B1999CFE52143D5AD6E4997F1B7DCBB3C027F261E19FE7B3D6450D4C780C971261F26907BA37D2F2A3499FA743FF0E93D8BB0791DC989C98C61D4457FD6A02C3913A596C4AAF785D8741F9F5CBFB8E77038256AB5988E870C27CAECC1C56C84511502332D6E77B25D1B1C552F26C3ED9A36559C99D7C02161A399B03A6752B20F539DCE00D25FDAD0291DB39F34EC14E4A86F74364CA9E1B78DCDD4DA6F0E719498A2317A49CD825DE57C33E9EDCEEAEDEFEBA7BEE9FF63BDE27260D923388C6A50806EF2684D09A2B8B518192FDC99C1FD49E5543C5F3E78BF6CC0C6971FAE2D54F6275323382BEF828B9BF8F7241850A55DF8249D2E4CFF800BB80E25F43ECE258E076A9634DAAFB1B4A57BCF1CB01A79F61AC182AB13F1B21EF3CEB2E53907C584B3E3FE667DFE3A004B9542232930365B2C057310E9BFDB628F4822D09DB66D1DCCB5FC43BDB53AD7AB85FF0D91DDB11FEBC7740FA535FA3AFBE9CB46E1B284D73B8F4E861B68A482F12D4F76321A08CE0D998D2FA0A2E158D798A0705C185D8D4AEC0EDEA966EDD87204C825CA6B44FFC2D9DA8557D6ADB2ECBAB595DF1961400A9EE10194ED6A4DCE16BED39F3D9F0E36F6B962CE5DEB1BF939D3DBFC557F55FED9C6587DE4834C13BC28CF8887C982F9171FEE706216F13E089ED848CF0034B225E9A9CDB75AD6AE49AD865F2FB06039FB84FC8A6D2C83A251530DBC448FD43A579B652893E3BE02743F301E5658F615494C004827451E5658EBFCFC87BF1DCF55FA9DC2D6D53EBB1E8B11AED235D19E693AB8FBB6A8F0948FDDE0D7ABE79916BEAA95E2F4DB1AC765A4E42C233FFC3AFF2A2E18C07381A6E47334F4D46B72671271D945D6243A5CC3E2859DF104D1B031BFB105E05F2B89630420F96352DEC138EFAED0AFBFBEA33C08979B3EB390A459B5FA5EAF913C4AD2A6251720DD6428624994E1BE7991C23E2884EFECD652796B416F274BFB3A60F642C13C9C87703D2FD22932D03FCADF86FF6C0CFE632DAD1F71295A6A82F9A52C441CCF18BA51748B8113CFEBBE6B9833153E260F576BD4C809FE7B3D6450D4C780C971261F26907BA37D2F2A3499FA743FF0E93D8BB0791DC7F3EDCB7E9288828E762E84B302377531DE10A18084FB75CF7321DFF45F1E53CAAF7B6C31038B16C7EE047DD3E641DB062C366B36081833BE21A511EF0751BF89AC5BDAB8D47B1EDFDF00BF589433C210CC5A3749C9F160CB64CEA314FBDE613EFF8C38A64AB71BAA4419FBF131D74E9897729B1751C1A850365D7559EB1BFD94206547113A6D9C95737EA1DDFEA72D8E681A7FBC76DC061A0642AED748C2A041FABE29CCE0C68FD689F432E3846237CAC1F49B2C0668BD5CEEB436560643AAFA1BF2D99B5268A437A92352044C70D538E4C6825FF6412999E4865938CC68437505FF9C22E9E7017C20AEE40CA835AB731B8DA7410796C6ED9882F6AC55AF932A852E2A2C03457DA377871493DDDF9F84924E50671AD8EF35DA44A0F4367B4F9A7E67820C765B1A3A5B28411910D0E1C5B8AA0376487A279D9A870E745EA6515AC7FA0E43FFAD8A291074CE559233BCC6AB7BA0D98818BDC577EBE3DBC58DC12960CE6B6AFA9EA655DEE9BAA1B6736889836775C32DC63ACDA6E9FDFE9ABDA9B378B29A1E421BC9DF381AA2BD7CAFE981C15E81D5950D524E0FC654A928FED21111C885C638D6367CC82E4586C27C9EA0D7898640209CB7EEBBDD6960C0F66963F33149431CD86EBA843D8AF6378190C171808B96E15280C215B264F14F81523A0D561C3D63666CAB5E63EC00953CC6BCEB76356288BDA1718C052F4E30D4B35A0F429B6C04AF1728FAB86CA4702CC87105EA25E6923345A076821698EB2F82B229DE06E63F0D7860E2A6A55772371E4D2181763C4E5E37EAEE0893613F8C1DB8CC7D3F5710C8EFF6AA792324E82CC498E573FCF3D137F70858C9020B7449A1E24FBCF133E234712738883E140BBCB614FF28CE7AE8995211B65BAF0A751345128B7BD5DF19979E9171A61320D65227B58A0F372E23D75F1C88F6738C80D5A7210E820CCC8597FF3A8F5204287BFE987A4326ECB3C3861FEA037A1494C3DECA5F5E830FB54CAE1644A9A5FDCFEF25742CDD5E368AC44CE7D8D2651415BCC9B5D744340EFDDF40865B919110B4927C60E7FC8A9E5E71F2C5F49AB715FFD44F6768CC7D3F5710C8EFF6AA792324E82CC4917131C52D098A779D3809337DC8B4406A7A2A13FCF164FC982907A66731C88414FF28CE7AE8995211B65BAF0A75134518331F6F5C8754AD195C04EB1FF1CAE78F4B1D2CFC0B9B7C411DE25099048F86044D3037684A1CEB58B88F91CD4968AA177E2CAA974E42234CD8C6C82B39AD1F4BBC85FB517D6C207C812B3A1A36160FF2E9D6200069F99AF5563F3A7FFDA6713794E122E7DFB4C5FC0182CC2131810D79918DA4FEDF69DBCFC7AD7073FA45747D8B9D87D9C2A5D3878897DA62031477FEA865AC1AB78749193BE47AFC8ED5E4AE102EDA9A3CE139F978C4147ED34B958C0D4727B90E56DF882AAECC04C64B3A3D8BF07D6B78DB4ADE52A22D48C8843299E74403355E92D369258D0E3E267E9A59B067C4B4E972FC0637469881591054122A257D573563A2D7CB926AC89E4F04996929FA7547F57A8CC0480AB5B5B4AEB78F69AAB31C36ECEBE215EE29CB884566825002DF8A4B5098BE8C3DC5776810D6A755496D67FB11ECE7E50E1EE48E2F6403A531BC31 \ No newline at end of file +435F35785E45BA969DB95FC07396BBF327C50F94B452155A10B2127EB2743F686695A42CC071322F2A3F2D1F5DF8371791ED1331D3FC196192B1F5779953C4F0A74B825A27808280AF58BCEA6F33B6E1ADAD9A4FEA22075DE973CA16897BDFEE04A404065A3A4A9DF5598F7AD6F7312B612AF89D455139A6E96EE884F1D8D0404461A7D04472C01F875989C600C5C9B312189C7E05A8D06DE4EFC9C90E9626A577255A1BA848653FC669B7AEBBB00F15779981DF268A9FB202B853C63846F9220895F15EAA14568EBCEE1BC2CE35FF12BBC093E81BC02C4B57C6141ADC72B847C36F28028FF2BCD60D3AA72F6795DECC1A76CB2FF432D4DD66B253EF88909FC10E1FBFF1E7FD00ECDDA622B307053DA10648F23A133ED170B473B3DFE288C0219232673E5F11538B54534E9ED45A296E064C3FBBB1FA78DBAD5B7C42B2C286502F73421F3F448DC33E402961487AE257935734D0E20A2CB8037B47F2305DCDC5CB61AB7433D63150AC02AC258753EFED9E078291139039A81DD9E4EFD846D881724AE1A51228CD2D9E9D6896A63FF00479B9EF00BBC912F38FC624364BE0A1EE50BAECA4BA62D36D460EB0B70E4706EB787C62BF92D5B24629918C85EB2F0F914E58CD6759D248008B7388192A731530CC6E5CCBFA6B2C183114F6B099D7843510E012C2F7E09FDBA63EBF14AF321B293282997D1FB2B2199D350ABB235C7D4D4C40FE29993F5CE496AD45A26DBCB47527CCCCCC993BD007D29228BE3D813AD2B133390A39586B974FFFC524A9BFC96F68F9F295CB88A795AD7AD149E8139BE057244B9C2EF569AA1515845D22DE3654BF6B6149AAEDACCB9AFAA0B08FFA8B4104D3A2237FDBF6AAC3A1276C577C37113F3F411A8F6DEB33C2AD78341E9E9DD342EAD3FDD9D5546AF9381E50890249AD2E699F4E974D8808F8858E9B441373032693DE29ED770A0B9A35788A7C37E73922A0757471BEF52B8C0FEDADA03BE09A2DE1D222B5A2E20F0E56CF834BE8C7057F539D73728DBBBB6D06C79583CD86BB80B370A8EB643112C8234CE533FA48408B3BAA71DA651E566CAAF893F51FFF2F278041CA7EE421A03E96178BA38D585B168B4DC1FBBB4DBC855C425F74BA510A6E150175881E51ECD535EDC6B2C7C817CD5934C26A3486ACDB6C9E685D03B552DDD2D8D6D55903FF892B68C39097F05F422C27032D7CEADE1142C13C778291061E4F6F933B4795AA6DDAF057D5F4209AFEC7043F6F13C4B447BE11A7188BC439DF94D7F409BD7FDCBB726E213E02E78212620FD11599686CAF57D191B822BF6A2C3E4D387A3CAE2CE8F415DA13D83809908A9C9EEDBD797F8A6A3E0DFCDEFEE108B54E0155DEFF67291E2A850332634B28A28A213B5F4BA18B5F8AA5F0DD11558F32FDD9E78D15F67B04B91894EA8EB4F6506D60506C48B638ADF3CFB651590EE5AE5D869DA166CD23B634AF9A19AF1E5B70935CF0508EBA0D8F7A0D2B8321F91A0DAF61B708743A6EB7522289561273504A2A24A67F4651DB0DCBD44CBB4A62B9648FB814BF7C6E08671C03C7E0D2B56AED7E04332DDBD804559236022A9A4B0AF9CB04DB49D43B590E50943E248F86DE7F43F3E865022D842AB51BC9B9ECA8E47DD8DAA0786F161C5B5EF3E8C41A809AEA96F6B185BDE4F8A41306BA471740E5A38F6DD320F612A1AC3F10A485485124952139A26D1B30E5C3CAEAFB462927D28404FF79BBF0FED9C0BFA41708900E89E36FF8BB460C3BE6D94EF67626126A6F1449FBBC136E67FC3239E5F3793FC9E235A441C7CD3DAC7CECB1CBD4080F12C4C975F053045DC2B333BCE3ED7880A8C604718BAB96C339C9273C2BE62663833A99178882E6BC0125ED14B99A0E55535C65011BBA82EF1D5750BCED03CD31A2EFC249575011F387529639EB74B70F888850A50FE9477684F9A4E81B780CBC943315A303C12F65565DE3B060E66C733E355C7907DDC8401EDF2075B0EAAA4BE8EB9755DD92D3F3282DEDC7CC2771E256C7B1FC8434F2737D4C9C7A55072E36B8D9C07530E5FFBC2D70E643F0D3172D5BDAABF92B21DE2AF93966AE9D88EA917939B96D0A55351FD08BE8A07102196D87AEA586652BC53DBBC9952067D8E9E88AE6D12B772FF10057EB2BE32F2020B0E63AF8AD992F4696141353568FF720E3901980B27F32B24B2DE09219FBF0FC3B9E0376F5026558D5752DFCC73894B4261AA83B0A4EFB890F7215B50DAC1496BF67F1AEEEA31B3C8590E5DC390311C920E5472211FFE620000C306339A71F19A396B9F1589BBE9249E2A7FEEB1C56B42B89806AE62ADB41BD1AB93672DF5B426B447984C6FD5D82B9AC47AE78E2E1B02CEEA327DBB8F4D25258F0A53480FF68C788F133F02D923CFF658DF19D70C5D5E2E90FF659E1A5C4AD87EC5A93910F883FF77998D036EB5ADD91A6F56A78ACFEFD564E606AD2C93AF20A65AC03A0FD20C97BFE905950B22C028314F52F671CD0B6A268703EC909997B70372408C8A595C8DB35972193A76D5A39C1DD190955099DE507DB1A0AEAD1D78104F551F2A5AB25D4C53A1A5858EB2D08017909C4818AE75EEB8FAD7DF222415F76FDDEEA46AB882D626C23BB19080950D1FBCC8326CEA8249F13C669BE3A19754F8FEBC08EB0C4EBAC03DB1E54268276FD8D260E6532A58E41CFBB4311A48DB5459A2CCC2D27AE527144394371540A0150590E9EBC82325B42E403E7E857463E5757952B856B91DC642F4E43322BF0EB882A8F6EFF306B4004F3C183E6D4E9A0E7902FE1EC779CB0A7760720E036BBDFE765B2FEA463F262D87DFA5ECD4C38093F4993FF57AC74D11224EA30584301851EA36A4B86CDF186C96111E3449E69F9426DDA9AA6C29E409B4CA7F8DB95CF4BC202736D3AC884B00760CEDCBED1210A2EA017FAE4AF4AC082AC1441ACA99692222D0D37751D4767AAE64BE13B4C774FC27628E018AEF407D1AE64F03F91127F1CB924E2E1EAE89BB1D7412C26C629203F3ADCBA9F03BD213AD4D583EAE1C88C20D80149386C566936E0916567774B1276D0DA8880BAADB28C60C99279002F795819F3D8E2C58A58200ECD94761960CFD1A0CA735D67779341890F7888D5D0D3EAF5862A57998D0C6BA865AC2FC671885D84516297D03EAA021920AF521D448D8E9EE71B7F840D8F0C93218EE0B5FE07BADE0BD9EC6D1F12E22C2598E07B060FADEA688B1A5534F051C77660FE4FF00F79EC9881B0BFCF13FAFCB6E18004188FCF8B8A955CE0BB3C9368D5545751DC24853D2CA9F8AF798D11FD9574FDCF3AC7A888ACEF079A7C28F875177B3151CAF7CB6E84238A901077945678ABD363AA1572736ABED0E056029E754BE2D0333D90658AEE3F797B1C054D026ED0D1E055034C7A56655A08CEBC556FBF6E09B36F0440148195CDDD775E02245891B2011E38AC3B89939D88B5C6A12EDA6C2124320718964E603BF4A5032F63C112955BE80EF162F0C81DD0580066291A92581545432A239B6670CBF6DF1DB42341605353CA5C08D88591B0B065B666C59BDCE627ECD5D51DA5C2E92C54CA247542F99E3A6D49825C8FA3688AE5091E2EACF22AE8FA5A4CD65631D1B6CC4AD98B8C89C90A8D0910D30B656465CDD5DF4B08710BB916A2AA87E33ED1CE9A383C19369DBD152C46C2A6FF075173138565316F0A60B4DD93360FC07396BBF327C50F94B452155A10B213E8F78EFE0C9ED08F588B02091B4B69EBAFC8E5FCEE4E62FA6DCE39CA1D6C924F0B4332A7CCC6A0ABD1A0F0B67CF4DB1609C13BAF685A8C9353A2EAC2C4D3F7257E9152B5E289D17BB5B73959A49F877BF7F80C76F7B86675CB1DDB21404FA79EA28B61574F456257300302421FC36286D56342E1351FA3A158764EE162CCB97543468558BACAE631282DE11B78B563993ED941ED3451E9C0C2A3A4D39F61D87CA012885DCCCB0BD17CA28186B8C9F9FA3DB738E12E355C3208E337C505CFCDFEE74331EBE36B7A90DF91AF028441A51D2198992F969E8C3E9DEF8ADF16E01339A2D701B4B8A89AAABA1CF26FA61F00B8C305EE63FDB68B40FBC3BE227E9ADD6E64D2E784F2B44EC6C655479919A11793E99F5FDF45945797E786D619935CEE9AF4BB059F69527A45C196BB89AB35C6EBCE7507C092679F2BA7D0841C6764DF494CCB8C707E245C8F10D48E67F1CAC8B047F03D921C35FDF481AD46B78B87C4BFD7895D3A7FF9DE1C29EE2C573C5FF628A28458AD7BBF5FF72CEB83153270C50C22A1CABE2E619CC68FB784030FC84EBBF12C207606751AE0C707B1927F6BD42640FB540F099816265739C43CE0E04E03B0A0DB3094474BE690439F0772A73E3BAAB8B40484ACF326918C0FA6A3CC22F39342FEDBD6BD54CD43646F67F7F3AFD5BC717FBB4F22CE891411C278FBAD56A57A64A1863FFB10B163643317B21D14854F170905CE2B0894DBCD6950130D80C047E379EA5D982EE5363F9D2A6457A3815275889F1F00BBAFC5265D1B0887FC83E1D24722BE878D5DA2D693AE0FF6CD2B7F49E4CC0EBA132A74BAABCF9C66242AF0143A01F2EA6B4163E9196015D10197C75196581E5F3D28C11CE7AE02B8361FDC6CD13643A5AFC0BB21351910DE2CA47E33BA5C0972A666B6CCE1B9C62DAA8178F0942C96A4EA7B5E30FD87C11180929137E5AA496F275F527DFB02063F37D6C29CAB881BD4E5AE9886FB9842B86E8DAA9176EE9C2448A80815C6658E4AFB2798E348324AE2E9F27A874AB05190350B2D445DDFBA4A5AEB1410FEF3C09673C986D741ADC2781306F2930B1CBA604B3863CE19BF3FD78FE3EACE85F7355BED0B41AB740407E919AB98B062DC824A52E72F8FD627B49930D1C818B5D298CBD2F24290DC65E14A683B100092A2A3BC250D2AF06983C79B7D467C3AD941229E9D89C457761C061228F88776ECC2C93D53D1697A1FB1EEAA76AC1BD3AF43FDCED744D9CB89E8A4C342234C4B66F33928D2DD2965F4CB1FB7D7A1524F6755BDFCFD8FDFCA8FCE99C67C7828CE650654CDF283314E49962A28E1F8A7D654FB9EC3B8CB997A1BD08E7FB34C44B98BEEED7B79588B4C92E2ECA0B4F72D73BC46113A6A6E3E17E07AAD79E7585D793E5CBF7D829E626C71A5C91611C0036BECFDCB2E9C15B0F52178F5A31D59548DDF0BA0F3A6132A8D8E469DD32E43779B8AD10170399CC64EBCF6B04E44D6344406807781D00ACE8933D4154BAA16FBFCDA5D78C94C55B0F52178F5A31D59548DDF0BA0F3A61E9590F8712727B0D463BABD0F964CE89BA3830E0A7794EE34160B704E43DD174D2AF06983C79B7D467C3AD941229E9D88B247251C5DB9248713F4CDCFD778851796140B75F704D95B3BFD1DB59A79A7AFE9196A205AD4B2E5031929394417776C3994DFEA258A0A2860C0F2737B2E0C10897D32AEC1EB91BE453987BFB0D96AD0FC0C44D60350AFB7999DE88624185E923276034DC7796253D4560A0F841DFDB016BD3CDD13D6561CE0A69E415CD30CEBBA9106D82F166A6D3E8FAFE3B3B1F7E3A12C32DE46CDC9F3B761CB440FCC3365B0F52178F5A31D59548DDF0BA0F3A61EE68A987833C77097E538B19B926CDFAA2EF4663EA8C7379A5BF67FCB84CDCAE5B0F52178F5A31D59548DDF0BA0F3A61FA99BB5DCF1AF52BDA8A3F2ADEF75FA67C1B0A68B253ED0151563FF3E9ED84B818BD8A65ADC13D9021E3F7DFFA80B11C31B4DAD3EAA868FFB3B8A3F728C222BDA7DBE5ACD3E4E7547C51FC3C5D1F52D950D5757C3C87424C73B63AFBC4C6AC50106F71F9BCB94E5DD2E7590F915EEBF54ABD7DFE15B25A944931B8A48D335677F87F87734A730E8F90CE07DE2EFE6D7364F10DD581FC787D1B4BCBBC70FFE0EEA85984CE65E8EEE415BA94FDA1CC76565B0F52178F5A31D59548DDF0BA0F3A61C50E253EE3FAD89BE6152298B97138219BD7E8E76ADD1AE54887575B62956805CDB759037797E2E265C7591D35680B23F32CFF71D04ABC967827DBD20CC6AB324ABD7DFE15B25A944931B8A48D335677C317E3E5A8F0A31EC1E20336EBCDF1E07A3084ABD06F2F799616BAA890461B111D5E409BE3720F51CE50674C5CE75F649ABB9892EBC26A3B4676945AB51325521B25805656A7F2C5C1F4C6763F52DCD75B0F52178F5A31D59548DDF0BA0F3A61F6523210C73BE3747CB103E43AECFF646852CFA6ED371B71EB48C7639EBFE67B870A05637CEF0A50AA603056837F1438E56FF31DBABE17785F4443EAB6491F355BB58B31A3538ED0E79EC3752CC1E4845B0F52178F5A31D59548DDF0BA0F3A61851B028CC7B792DD33BAC70AF19D92C0078A5F6465DADBF7A4B77CDAC8B435CD82FFC7AD55467603E162F5F023C245607291A6F92798A2F10DEA3BC2C4AE7F67E62AA9F07E966C75AC39EB92C2D6804D73A66CDAF814D9C3951EF3EAAFB37CF80DB60ED2FEA32964A78D91D26C505813F28C0DDD34A7AC1BF58E0B800748F57F9CBEA21698A4E8B8DBACF81DFF89B81D668F097B50F3D2C53F6D5BB87BF26F332BB77DBB8FA16F618B2623503825A51FBE78F5A9FD23E4F66A4F98479F1A9ADCE09970542DADC30D964CB1A6E2BEF2EABAF0AC194EFBB7ACDC0CAFC58AD4C89152AF525B07851D7CA05B0F9944FCFB6EA4B86CDF186C96111E3449E69F9426DD11F08A32C3CE3BDFF37D6E3EAF2AEC8554E5F5CE52A5F92A9BBF9500687796E07B3DE3E23431A700F19B9907933147F8C1C3B2FE45CF2F3E244E6B870164173A924DEC731D64ADA7D6D100860356F092AFAE25926D89EAE216E9C94CC089F18899759E8396F5B5C1823C607B153AD1A0CB399B283C6B0FE993BA234C52CED8B4DA8BB5DDA77E8A59FEC85982182E8ED31E22070E06A125220DA1055112C0430CF0CCD04BB0C9793824D458A0AC53D3B7EFF4D3E7DE93D0D718D2035503A5099AA00B6D34D85F57DD96EF6522D370460D046FD36FA255D44A1F7C8E9DD49B57C7769A0947A5C2ED31055A465A5E8D3841BFC34E9DE955C79ECC5BD0EDAD29F427C32C4400D24E24F9EFE247D997C539011A472F70239B6FB2F895E993EB65470502CEC1E8F9FD6222E3E4FAACF6EDA0D8848F94DEA596BEEA61D3DAE7ED2713AC6C0134FC088050348C7B198801524603FFE17434BBD6A10A72E712EEC389C75ACC00E8AAA665C8418D1E014487C85C13496C31DFB6E6DE94817EAB42FB08AA7C02CEC1E8F9FD6222E3E4FAACF6EDA0D8D4887EE342362F29F64903BBE86753D8F918989C7F43EBB9497C7ED8C082881E321EE07FB62E7A4D84CDEE5CBFA9551C37E10CAEF20F2FEA31ABFA3824693197DE6E99048108EE9D76FABD77910181ACA7A274E12E59D44667438E40A679A04CF6BF6AB46440B65643CBD3F9C1FF0841BF3117CE42D12295D680B64976B9AFA359F0289F2CE66278B7CD7D6791F35249C36547BF8D6B3F8EF31AE86C5B9A1EA35F98FE01A31E08821058D69AEE1D3DA9DD80F93EFE8261CEF47DEF66072ADFA09B27DA881917A28E8253577A12AA662C07C1D3755E979744152E7C2708D437A77AC0AEED3B17104A27EF3E9E62C276BFDD80F93EFE8261CEF47DEF66072ADFA06D466652AA7470DD6A10D7487465F78F1B9208CB7B817A3F59C802350BBACE174A8FBC42E284F7F104802C0695E44FA1DAB2E67B6EAA637EA154F2A33A0D9D6613069C7A234146B28B6FCD7F1EA9F8F5B38922F55E96BB8A50732B5B8385BE3B8AF6FF3A4596FE7B6626E553A5EEE53DE7C1A07D2A16C221EB34C037AD1F7AEB461A1DC99712A45E829FCA1166857932D405BF384A7E8CA19CE4FF1630A3721BA1D7F58DE5300FD70AA6C91F4CBFB1B745254FB3A5D136C29B458FE41CAD9944FAFA513893A78D1FC9CC74C898E11E6CAC28F4AD3A85E574B45E338032B911896FD00E2581218A4A890F3F0C6F4BDB5DBC0A777C3FD91AFBDF870BDD9BD3A2DB10A4E3D08FF95F4D29845B4A6BED699149BD592DCFB06A21A5CE706E3C8B0AE2D9F6AF062B51B64E0A5FDED1D1A738B44918E6BFCF3ECB3A3761AAC73F6439D0C27B9D01CAE03D852BB8F3DEB1752924C6020A4A5DC38C78B932107660436C74333001E6B4A3E6FF9EAAD620029364B73A43ED596442381CAC1E74CBC4CCAAD5D596E5C1869C9A043E845DD48D07C57883879AAB0239B30E055EA80394CA2450D293D54FBFC411957EA632E8F1BDAD0C6F63B2ECD10118F9A5C56D463EF70E6BA481ABCFA29330C37283DF676101CD5FC8887379B3ADD6CD2C46D1FA6FAB4609CAE2921E1F4D6D21E0D13D0B689F9C702EAD429F0C89118ED0677E51A10727B8D0F7E24DF323CAE93434E552A4AB81FE31284D173AB286A2F0956E04C3956ECE1247E8ED0026C7A114E55CFCE24E2A506572CC77481EC38986C956F3A489B509851460D695815821E49B70AEA3A1237EF0CCD04BB0C9793824D458A0AC53D3B7EFF4D3E7DE93D0D718D2035503A5099A579BD3066E00A2AF59A770FE7E7259E6C66D53BCB6F62289C02346C3023196C94D5337834CE431DE4479FE150AB2828FE48AD42C771AD65DF2E3F4172C12ABD7B098B37D10BB88B63BC5E3CD49E85494BCF650C9A52C3A95F21E43415D231FB049A80138855720A4BAADCA8A5D570BBB2A25ED378722038D6FBE874F6B645DB36FB638A64566AE30B967EB1F36F958640E50E5BAA6CC7364DBEFAC85C3298280D553A879BAB18DA445B66A88041A8117398A0FD144653BEB6DCBB63F27F4AFCF5B518754369C26FE4396FA539A8DC17E07475E8F6EF88303C22C7CE7559F14A925644D7DE518D971617C7717437E34FAD9E69A5DD6EEA6AC1740029534F6D4C6ECF295DD2D61561CACAFDC9BF8858C29E73C54724E3B3EA4437845C03ABE8912E31B254CF5C383BD50C11B039DC6AE3C11C75B2383E21044F97EA6DBE2D02F80434887496EBD904EF99C10ECCFC7C0CA49692E89D41587B4604352C9B4C0717C48ED8631E608F8DDE85F56FBD9952F9934446856DCD03B2DAA5A26951E69B3AF470D76201CC7EAE77FEB4F8623CBD5C7E6D2A61D3FEF6EB2A43FA90AF9B62E0AEBBB9AD04845F8E803AA9F2C135E19B3DA0471DB8306F575733C38CE882A2D5A6EE9D6188673328FA453874085F35375710B2B16207910A7C6BFED365BF886841B8861B240626F45C7D542B4E74E202F46AC75CDB8D2A4153B8C7796D19E12736057EDB7581C513A415E4B4F7B156F9E4D0D2FE48200851E23CC3ED3295795AF84D13DF95F8F22214639D6AC48AE4176B8DB0E9926164C18EB7A152B14D1F2290D8E7D38D63759E30E2F8C4CF5B456F8B06DA8C3D768B22B864C89E1A7A3A1146AF37ADE19DA4A64B7C32D5790F287AFB88F3F110570373ABE8877D2847CBB96A84D6AB67FD90C25CF51AFA84EE0E4849C4A9BB0D66534DEDE64620BA7D6E20DD3E41E00B6798565DA910189DB3BE4BA9860894A53B9CDA0918F71684156CF631280BECD77883B477E387956D66E496218B8510894D07126785D43F486129A514435F5D3456E6DB4F10FF02BD0D3FAF705E32A432D27DE1453D495DB3EFDF1F25B0F52178F5A31D59548DDF0BA0F3A6182622ADEE0C2F9D5CC6EA248BC8F3E4A9BF0C019B433766DC8D63DB4DFD02C61C11B08C25FC30069FF545AE0E10A1379213D437DF597B5BC17050D28B3A4BF790B7BDC7458E45D508D1DE6D224407667E13DF33095E5985E3B2CA59EB613CE30249BFB072271DEDBF7E274DBE3B82D9CA652EDD0BA47C01D922ABF26A53B61350B1C1C4017398A092ED179929A5D6BD935F04948A5488AC8468967832A2C5D200035583584D8A7B7D7B8D98F1B330A7ACE2B6FA4E99157FBB988798D376D353B4E4E2670DFFD12B1850592AD7BB563D089385D155EA7B2CA31E0F60337C79500365AE9561B2046F54E3A4B2070965FB393DEFD5A50A882DA23D3F443D909EB58ADD9F12F5468A65286B1795F0925A3C01D729AB9256C860EF0505DC14F386376BBF588CD1A13AC0A95C3B0B7118C9013A8C1CB9B93EFC5A07BEBFDD2754DB6A2C0A089D17F028E78C40B172524C3835E1A44CDFE00EE3C48E87B61BC74F975E412A8AF1363162731C7FA5038C29F94B82B92C7731F824F910CF51D2006EAC09EC7F545886C93A65208E946CDF6FA6126559A0D4AF6FB48B7F754E31851111CC5B054A830F94B22856BBC9866812C49DFDC7F04322D90FBC0770751ADC155008DA28B2954209822AAE05AC882DE03BDA2E9D22CA0C974FFDCD176E373386E138DEE4A726F5403EDD3698CF8C4ECBC36D9418332A00F932CF66A809C9C4E89F47C5D2012A5CB3BD78A3714D202454533B7DA5C2E92C54CA247542F99E3A6D49825C8FA3688AE5091E2EACF22AE8FA5A4CDAE0B131F72A6B687544CE27280678CB4371AC190D6A13566C5B7BE108C07E04A10C26F008229CA00B89BE7FFD70E71E365457EBAD77AF9E2DD10401EAE6FC8D3213BA4BCB0BAD7986A94EB333F88940B640B7B0A6CDB2835C9A0EF3A5241774080DED89C9C31E4B3B7712D99F8DD1493A5AB7CDE8E493A08784794806F08383F3524DE856792FCACF108FC1C98B22BBF73C452D2EB5EC449D279785792274ED0119B67B5AA6A5158EE119DA181613F375203ED8E7D089B11059174BADADFB285D07148F7DE01B41AED70CD1AE270AACB25C43515DF9D8806E6B7EEB2AEBAC3AD70D9B8894B14F2EE058DBA9A30E5852A6D8EA122B04E5F03DDC6DE4ED8D3C5B593648CF930754FE985CEDE0BAC5AA107498C34808AC02AEC8033B95A40F7890ECD450BF13F9DCC6EA215EB0A167A98D726A726AF076CD83676EB8EA6EF6273AADC179CFFDE5BB79EAAD8FEAD7DFA0AAA3B78D887D3BACA022734C5CA856EF9DB6C041E85627DC21B93CBC6F6DE4533EE0C6A63D53ECA9AE9543D4C4A8F39D700288304DBB434EFCA3465E73047DDC138E59DC09F541C12F231CC3CC52FC454BFC489A4E0AC023596F306BEB658DB7481ED4C7665959A33E96476BBD0EB6E12B11E7E1C2F161F7FCFFEFA5C6C893C2849D994504FBEFAC908182AF541CA4BFFD9FC5879BF023F807420B455DFF15A3B3B3C31D98B046520A06D81117C4528903E2DFE431AFEBEA679B3D39A06265570490897D32AEC1EB91BE453987BFB0D96ADFD8199703DBD2F5EEB0C5B3EC37F79735B0F52178F5A31D59548DDF0BA0F3A617FA7DC55811EBE5BA6072440B2EFF51C47A53EA888AD57BF23793E671E6D495631BEF7704D01576F6ED6B1021A22F064CC69D2D157D182F57902B968C57986DCEA2605CC04271C14B269CAABDBC46585C645273D4F8D5A02A0940BEC17CC0A7D68DEFD5059CD66A112EF30F11929E95C80FEDA4E527B210AC6805F7CF1B5F327686AB7F210039B3E28B057D5E453F2A2BEF2881628216E0F3C5E6BBFC1A3D1B4A95B7088F598D07BA9AA2B05A751FE5A4514850F937B2139AE394BD7EDC4D4D98BCF8A573F2CBCB7E2CC288ECF7FE72B99A93CD708F380B443EC4AD28344C3E34F2FF1D7CA058C807521B1ACFF55175177AE2073EC3351734D8278AE66BFD8E68D39197FD11759CEEEE718D7CB0A20F0570DFE6C68F065829A7B7123D9F1E2E734BCFDE476CDD3C5108D6E801C821D9D9B11B6FBD79D4AA9CF4421BA0C6AF8CCB652786DC8D17C788E78EEE76738DA1199A898FF18C20F4D56E0BB9C6981A299D9F294F13A902A7736D7A8EF125B0BAAB2C06F1CE1F93BDA12ECE709FC7BC09D82ECC0BA28C95BF795B5580395CA01E7B916E4C63556BBCD7ADA11F6210278BAE02ECEC8E0F8497C882EC46E6BEB9D6F239D5593AC2C5ED9233E12545254FC78021594D825B8B0228296EA7D83C618A46617046C8139C5DFDF65571924186B7743769FCCAB5088003CD0E0D13A84A720D807A1C8275AF42A0F1E38CEBA9E89CFD066DD43143BA8CB2BDDCB70E0EA9C3D050DAC06B957C3FD42A92B17733A9669CC8825EA050F0897BFB8654CF73FD3103D8E2C58A58200ECD94761960CFD1A0CA735D67779341890F7888D5D0D3EAF58F7BF2D1CDC34837FB2DE4CE5917744F501A61CC88C8B2DDA88922AE71DA36A0F4435F5D3456E6DB4F10FF02BD0D3FAF71D813B7ACCE8E62EE036FEB59A615A85C48DFE1E60717DD1252497031EA5BA921A23E25B7759A6945327AADF2DD88214AE516BE150ED58AE2588E9E60094D7048FFE0F79EF021564D032E21446D125C719E9F92579157E46C49EFC03F2BBF46364D076BBCE9EB7C4D0E9817C58DD2441C865F7D47AB655C4E4A9D44F6F6F0DC1E928D9919BB223FF7DC2EED56A9EB6A9427629FB1F2ACA6BD8694D3915A5EBD8C6727D76F62E0ED33025CB0A96C13FB8358E4E4BFE720ED34AEB93CA3A2737D81586B6137F7449CB865BD9DCF5B007D59DC462B1F21A05374AD945E7892F084A670F0AEFFAB2230848108DAECFC19A5EB942B4505905296716388EEDF0AE0046CEA6F33B6E1ADAD9A4FEA22075DE973CFD3602175F2E21730C0A2A2EED60E08F326A35CCF51DA5C2859688F5E1F5DB16DB9188061D7279652BB5F2256BC1F538B026739142481952090A0034BA90190127C76D7CCAF353EF305B45C4E73E0A4B9B2D09D5BB07C43CA57844AF742957A2E20A6721F060A8B75A9FB5F72996637A507316C08D4C0A5DD0517832AE2CE4DE6A0D6EFEA98D1A2D10BF7A767F7EBFACE7F1730AB32D79EB96A8AF011B94CD69234B9846714C72ACA1D33D60647CC411DA5C2E92C54CA247542F99E3A6D49825C8FA3688AE5091E2EACF22AE8FA5A4CD48ECD595B525FB58E27E72490485BFDD6204C544522CA980EB41E8CED6912D75F57C23E0C19AA7A1A27E34B24E3279AEA289924F6E23640D7D2176D686C68539A1350FFEC701C2B233B14E09496C937EA6D457FCC1FB1FACF10C2B7F14FE1D2B2167F159E227FE8D85D1F305413086E863783E3A3D803312512FBBA240298A425B0F52178F5A31D59548DDF0BA0F3A617630D9B9740C169D8B4656DF6008E82664ABD2A15AF8006EB29485D159B6B9C36E982A4D6B76BF9EA05B300E2470C8F472F8FD627B49930D1C818B5D298CBD2F90E144C6B6F19F93E6AEEC0189B8946CF8C20613CD78024D3306C32BF6B74B61E05AFDD34FBDAF51C2F812C62DF2DA2FB787132026B705FC10D9760DFFB0DEB064CF1CEB156C8E1AE632F49906B1E1EA3475BB1BB36E9AD906CD8CF36559A2D8046FD36FA255D44A1F7C8E9DD49B57C7769A0947A5C2ED31055A465A5E8D3841BFC34E9DE955C79ECC5BD0EDAD29F427C32C4400D24E24F9EFE247D997C539019DA222E611379869AD081ECFDE5823C789AA97651399F8687572A5DF369E446C1C984FA7A917CECBA539AF7876F498F548374647CEA76FC7A51CE0DF25054BBF64D2BF3C4AE3D53E5969DEFFCC63D320848F94DEA596BEEA61D3DAE7ED2713AC63DAE331812F6BD3C6D75B795D96CBFF121AC3C56ED8DEB4719E47833B745267754A4C481C18DD50A161CCB03D8A067FBF93C4ACDAE0EFE39DFB12DD21CEA7C5C29441C7100F3C60878950202F95EA7EDD5367A3792298562FA882F34BB97C4976F74FF7A2E7715D2D03A633AAEF37B6027C66F78001BD6AEF522EF5EA68134C48CBC6A5AAFB7E6947F396A89DAC4857DED3EBA406908C3EE0A859A6573932409D841638D34583573978281343DF9C3070E023BC7653A1F9365FA620A0DA1B2EB4D366D0467EBC26DD04A76D07CA2FF57D285B0CEDF8FF40AE385DE1B5DE891AF68DDDB0AD8063D9C4EF8D416A6E378C60EC3367260CAD219209FD8589A6608D215E2CD27B56E4D2E94994233D78DCD479AACF3695B5EDAA77ED01260D7A5265DA5C2E92C54CA247542F99E3A6D49825C8FA3688AE5091E2EACF22AE8FA5A4CDAE0B131F72A6B687544CE27280678CB4371AC190D6A13566C5B7BE108C07E04A10C26F008229CA00B89BE7FFD70E71E365457EBAD77AF9E2DD10401EAE6FC8D3DD80F93EFE8261CEF47DEF66072ADFA08C4F39C61414EA2550ECE080444DF2A0213BA4BCB0BAD7986A94EB333F88940B640B7B0A6CDB2835C9A0EF3A524177408A046EE75B6739A7A2DCC6F3AD8E9EC7931518157EFABE2D82755B7CC4600A4EF8DEF8A95AA63D95B2B79067729A2322C2A7C8EED97FAB7A8E8735A57AB36154B3315E219681F77F05A8631D62FAFE55445F4447A0A91F1A23324C0C24E11A1D7E41D9758D5F016E4F5066371247CA28EF371D5708E10B714F4A38853D9D8E432A693AC2E157DB08FF30FB46B8B877A38A4297ED5649E4EFA63886F97BE49EE9B498C3322A9B946C06C5CE0E5CC9AB1FB95EDC53FD6E522BDE9057A2DDEC95942FFEA57A48827C8B74D2ABA4F065D1E6F48EBA8FD77CED033270409D9618F9086A56D4BAAA0E666F5D680DBD228EF82DCDFF67BC1A014E2244B99CEAC5CF3E83781BEEEA39C6291E6F16C692B6836541C4FF058620F17D8CDDDCEAA2F85D37255C1484BD3CD22EF2AB90D67067BCA6197036D99F18228A7DC2B6AF02FA4721357F95F736E121944711125C933C4F357814E6CC29C1918468D10B73B902CB05C196AA1BFF2EA2FFCC32E443EEE7F35853436B632DC8650E4C0D8BB8B99696FDC4EDD9FB35D048760FFAD4714247BE142E2891DD3ECFB11B511BB85ED29908FDF16E36BE1808C866067F87D9C9287AB88D6D440F547256240EBC9EC611391AC64DFCE9309C150B13A3970D58CA61B1831580FD6877AAF5AE5B9ABBEB8E624CEBBEBE7EDF3A2681A47EB0172347D42638B40CA4020BF1197919F7BB33E99F5FDF45945797E786D619935CEE90EB58D3B959BA8FD973BACAF2A32011B6A531C419C9F0A65E1E76607F0CAFD06D2BD87B0CC7D0B5E1B77F7C78665B5D325C43515DF9D8806E6B7EEB2AEBAC3AD70D9B8894B14F2EE058DBA9A30E5852A6317EBA7F3A8C28C5474BBEF6E4C71B24B17267AF12567255495AEFDAE3F3749E8336BFA373B9FD1C19D2F8F3955F5D830310F2043B718B4D57D689ACE1F41DD0BC91413973F1D3A4B173B02ACF433F863C55FCBC951BA1F770E25E8600C8131880FE9D37F7D00047EF6CDB9EBD9CFAEEC6DD840A89D6FA8D9DDFAF764255519A99CA040A869923FD43ABF31EEF7E9279EC27736687C42807DF5E4551AB551C05DAE114B8BA1A9F1A2DA26B7B1455B1E2B121D208F36A1F69109894F04580169A9D6793B0FD223CEED13A1FB69844E7DE8CEAF168E331D6D1830701F914A26656A800B525F777E2F96FBCA95A590FE8BB74D1AC98D9D158ECD57B03BFEF8CD823B7BA04100AFEE82B76CF2B9FBA1D1B06BAD069B4C4D08819B9F02417C4E72F00CAFB228C3806E81352733AEFC910DA48AA96705B2E05E68FCB314433D99AA0BC0D7DCC01E337840060B7B48939B816E2B68EE76AE01EC52257429211EF7BFFC68D3E8C4F4735D77661B1F85355990DDDE63233E2EBB17C11B8180EDA9A89C0482A5AD263A7097436D01742E1CE9986466E974CE29BACB0B4FD66D7BF6039B1ED9F294F13A902A7736D7A8EF125B0BAA944FC1A4C5CC3E0DB9A8481485D8528689CC0B8A9FDD4E7B570CE3B4FEC6246C97B4A3601BB42AC1378FBB68BD395534AF4E5C13FFE1207755A2895A9B8EB0774838529E781022A1C80EFB9A4ECA12D20AD938DE4CC808CD99ECC0F389F2E6CEB9B3A107733B86AE2D695912FC51D4E601511B05AA0B6E75F11938C8AD6C38371275F17A3D727417F102A4AD2B1F87D79DCE910FC2CD36C575F33143D1907F852B61FF138FFAD6AE8B58BCED4A1FDAB82A433AF2390CB56BA14CF55D0EC52DBCFDB55D49F4531E822C2B25A09F48A59C01CBE1E6C21188CF2DBE0AD7EC96C5735DD641CC5E591EF327B10568F07C2C35C28B783097178556424C4531BA4B602C439975C682ECD87C21E65AC8BEB0A5E978AD57EAEBBB1FD89D2A90CD2D17A1639B774CFB632AC8D754D6E5EE2D23F9471EA927A331815EEDCE538AF03B7DA13449692E89D41587B4604352C9B4C0717C79F19F146E372DD214F8451590DC5D2FB01C75FDA21747B15E7E98733C320D31FC123EF7DF9DC9CF9D22E96637EF378987598E649BA0FFC8C1816541B4C5CF8D5E06094ED40AF35AFFC4C92CCE7378D32487B1546CDCB27A53DB5257BE243B58559E383B34B922080268B98D91CC0982EC8B0AB75B3FC3E41577A712CA6D320320BCF3472C5EA86E94ED1BDC211A50252EDA4017C5EF9BE3811BE77A221B0E9A4A0C5F36AF4AB4F39AF51D575A3BF06BF2F9C2D17A98776A1394FFCC0DC7BB9ACC6C13A7F20A1403C9A57958DC53A0421F4E6ADB60CF94D46ED28094A96639F119807E43D844B84482070858B89B9D43089CD65AAF33E33EC7DE3F14DD59F309FB8C37B5446223ED392C9749FB62429E56FE066BCC427AF926C3E9F72DB65F1951ADBB5E7EF8051DF2785994D9D08744FB3893FA40AD05974777EF96FABA3BA6E99368DB582B51966E470E17621AA4B0C23EB7FB26B147BDB4776F15E3D187767634819F59BBBAC98BF65873C48B7C253DB025A4A7BA35DB3D172868CFF12EEE83E78120391A6F69C0605BD818EC7FD7FEAC8D57F20E856CC111587553AA0E67D06B0FF484DF6FF7ECEA4F665F7BF03C39BB3428ECB4EAFB8CF06B1F65DF4FE0C245BA22CD9C64B8A69572B7BE140A68746AC94DE3B5AA81160D326ACDED65958625B8D871CD4D52E9D71D6037B3DBE96BF0527FFFDF646D4347B9B6D633958CC23EB7FB26B147BDB4776F15E3D187766AF6B69824855FCA7782ED76717D96A74AB0680AC4387D390079F45049E67634557B39879DAE397B9119C03162BCA7AF9160845FA656C910A87D4E5A0DF8FFC20D5BA860AB6C2BBA04BA28E818D119A87D8556E35CABF6E2DFF1D75F4FEAF5EA12FA6AC19938058926C1E4D4AD3D1305288BC9DD983F5FDD839ABBE82B4FF21DBF9328B99C16A3C212D0532181A061A4263826C808ADC10DC8177852077C3D95737832884AB788888F3C9ABFBCAF9AD139BB3428ECB4EAFB8CF06B1F65DF4FE06DEAA2B49B3CE7A26101FE4B8F695F948177B2220888C07A889503F8875AF2859BC094266BCD7A6BB265B974AF7141B0D4D528B339D99F2C8A7BBB5D3CFB5630E1CF67D1E8B8586B6BF17EAEF0187950529F1496A9E4A01496C7EF9700804FEF6EB51C4A5C1BCC2921CA8D947F2724DB9F010F62F081828AC896028AE6B9FF2EE4A05EDFDAD29949A6416D93D973DA149F010F62F081828AC896028AE6B9FF2E43FE421CB812C6736ED449E05EA0AA7D39BB3428ECB4EAFB8CF06B1F65DF4FE0520A8316264FC2464483945B0B567E1CA16CAE87DC30A142EE104940FE2A1FFC06CD5E8F056262AB1C3290DD82ADA1E2BB102E6C96196299C036F93B0E9C9BCEDC1EDC7C415AC0D44BBDC5923294C473A3166DC2F3A0C338281A095FC9003318DDBA64189E9F39F65E203D59729FFE06B9B3A107733B86AE2D695912FC51D4E65CF6560695989E6307948549F7A404C537C8A0BA2A10BC084EC9C41E13C8CFC8C5589ED209CD1E02830DC6DCDF2957F90D72285B261D97AAAFFB29F3D3017B0AE31599C8361179CAACC680DDC60DAE5FF90E202A70A8860FE4BEB50404D32952EB1F6D1F4BA5A3AB489BE92A87C5BC9C659D8FCBFA632FAD238E874009F6F579B5AE3E6CA44F68104DCD6DF61869959AC6278154A07ED3CCBF1CFE879C7F59C0FE672F5065AE00668C41EA9A5FB8F4EE7F4D0D0949CBF5E8533862B7FD198582A1C8F247CC7CB780C54D658AEAE7365F5C31432438C46DB7E73994CE33B356182BD4859DFEA352845DDDD367EA48622DFD806D55C9F4E20F12B7EBF3F1BA8C5DF56493465EF98E516179F96A34B2DB0AE5A57729FE89EF4F55AB9DBB6C6C849ADF63B229FBBE3755952AF53975A5419CBDFC05728A042C281821E3B48676F718E3F1B8DE4062B86058CF16E12B3DF98E1D0363094C08A40AE9F0923242665674C4B693F0C789F0677B1FB1DF0321DDAA3BAA356C7C13F38D35B4E4FA53E6D37A19807E43D844B84482070858B89B9D434CD33EE6838BCEAD9E4725D585517082E589EEF6554FA5D57BF2C2B8B51A111E2680EC36750175BD9CBF09788D58E8F294B1B40D3340C0997722398FBEFF26BDE99368DB582B51966E470E17621AA4B0357C6C35A118DD8078374FB16D775625BD71502C091747F2837EB8233BA040675F56EE92C9C21F4FA3D566B0F58AEEB4BB4E91101A62F845CF8CFE867C5676FC589FCDA2C9E3C7B4449E2E2034EDB517D7506664B389CD225C0E5ADD4337A0BDD8A0349F2CD4D07C3B5B20A9C94E4A9EE39CEC37EDAF82480550BA7979D4A6596A022F5747C7767398E3DCEA56CEF37483A18EE239E82D6E949E27E39C5F8DD1BAD4E847E6FEA479120E5D4CE50C069FD0E118B176DF018C2E9560F8B8E7B545DAC8D8719E2C9E4F65E6290E694F86F2E4CE7AB3F52A354E142EEFE1F6DB9BD6552447933A5D328C2DDF4F75005EE359D54D1FAFCB3FFBC0E0E57492E7A29569357C6C35A118DD8078374FB16D7756257916BED14DC892F03CE6D89AAE35C5EA937538D53FB8B1B998DE89E2C3D0261FC022426E0EB711DCA89DD46D69369595E57D53C03E55C8F18725E07CFFE6442E5E32AA05B15F503B403059A9DD9651FD27D2B885DA5C522505E1F5FBB09C17FFD82BBFDCC430D63758DCDFD8C5247D644C3D559108EC85A32E9B724E2AC15143F02D7AF19FFBEFE70D75BACCC199752EE4CE7AB3F52A354E142EEFE1F6DB9BD66A888DAFBDF4ED7893361461F9E6F43BE155D81DD267940C1D2386488E0744089B6768CB0BCAA826AF28A33DF5B227903F12863ABD8702969DFE677244090B7B4E2063B7EF13AC6AA0E45C5AF22DD3216DE0B4B6B5532C75F2368A65C4482DDEB7D53137CE0A99A949618DCA0976EE96AB4FA47D42DF231CF3440CAA39FF7781AF4E26F76DAD47E2C296FB8A972F272137FE5328C16CE73F89CC149BB188545CFDC8923185FD01E1DEE40BF0A070AB5DEB8313DD2833211216BE343433DEA39FEEF18EC756A90DE38F63899AB05EF5881075859E3E6A91ACE9E0A408E0757FEEF04A74EE84B37B2E508C5C8FD67D8C6F6B8E3D6F1A6A955835314EE0B5289890FB910BD0C8AFE1A00306D862A9D3732C42C2D0EDE3FBA1443AF2F0B733D0C487E5D93B10B0C45217D6989CE274A83479CCA64E201E984BD5F4B111D689895A39E2583BEE800C9D0C1C4F74697CF6BFC20D723F7A221693D33AF007E4FF4C3967DE9AFAFBCD4A8D348E7D3C53D8B096BFE155D81DD267940C1D2386488E0744089B6768CB0BCAA826AF28A33DF5B227903F12863ABD8702969DFE677244090B7B9AC0812071D2F23539D5E0895219298A26E4F0C7F389341C9594E71A12B684EFC825072E503ECED440C1634BF31123CBB02BD3A06B1070452AFAEC843D0E54487E041DBBB23E56EDF37EFD7B133E88339C1BD4B4266271634AB43F61C17978553AA857E0173A4118001559480F5F9DC3B179944B79C9FA2491CAFE41C56D21DF9557A2658A0FD171C50495797D0ADB0DF13FF09F5FC2F4122F712DFE999A5F8119A52B444BCABCF8AAADF0D9C2F9A64E23A41F2720D95ECBE9FFBFCC0A5F593E2CAB7F0BC7F4A276777E19B7B4C09FF1589EE720F2132921A49A9A29698838F658E1B69E0F738F47A1EED119A916B538CC328FDE0E19FB158EE9D04ACE2286A6A716AC52E292FA20F57B5BF723717215F683698A3217B0880AA8766AF605D5BC58F6C9451549A1516E5E2CA37ECE1F9A289433DB28A8D06127C516335EC910B20EE3D9D8F9BE786D1CAA957D8A32A2955653F3CE8026F3D7AAFB85B738428732E45ED1A95CD900A3EB18603B5027766B9860894A53B9CDA0918F71684156CF637ACE4A690E6D52F687DB850D3BC970B7C20DA783D64AED8D98655B15807D03C77B3DE3E23431A700F19B9907933147F8F85A3BAD3537AA3CABE5D9720730A2E3B86D4D6FCA28F12BAA49D3BD93BDBF5F516F6C02F69E6064FDD5521333EFCB21AE59977C874F2C2B01DA361922FE6477CE5929FE39750363EA0A812451704DC646132035F5B13784E4169351DB8CC05285BAD843FB04097BFF444B1DAD1C56E82658297B26C51434569814B76882CFAECC9149BE5B15FA8CD666E5DF693C6ED665637A0C01B88753DCDD949DD4F4AF02D8C48CE7DC2F912400916BD4D8B921C806508E37843709568FF38810A68A6874F990860D7234811D2E8EF98951248F557F2375DD8E3172472876273C48CFB58FA65A4BAEDFA04AAEE677475D538192DEE941E51ABD98559633AEC8CF482236E94B0DDFDA785D4C730E61D330EEEA33364F7CF47EAC5D5560ABC35B95E76A45C1147E920968DCB6F912DFE114D6D40CF28051BB15D0ED44CD93BBB508A7D79DCF2F033461E32B0876A0EB74649492CE53F8A273635B09A4A46383CF5C7FDCF737CC010C03DC3C869F913CF0735E04C6941610E54B727056F19D7E92FB5ED9206B49DD67032DB094CB4B131082A1D1BE021EEB9E115D894301DE9C9BCB27B60F732FC5DA09AF7DCD7C5C4262C0E5EC37E97934526A32BFFBF3ACCEC4DBDE5B2D54320BB9275B196E1DC41EC5A7961C48D5283E8369F1FE554CDD06F4AF0D139EBEE665A0900F0453F6F976A07B01F6E4BF06E66656C7F2097F3C232EB4234A699F016499EFC1734D340E6655771D5A3400FF5B9108079986D4E18D261B110FAA41F7BA85485F95452A247B541EC2A206CF2593C9E618B892BFD5E4740502054CE2F4D14D0B7842D88B844AAE362A7BA4B4C5B95D1BEE3BF94A8A5F2171019E9E6467006479DF15F36DE3D32A2B113EC05FE09970542DADC30D964CB1A6E2BEF2EAC6EC558B2781E0A73642F24AC2EB76A82E7B7E67F5E7B09E42978833B205CD1C5D28861F0CDE688F8482E9B236B937984146610D081830806CCFAFA1FA0602A27388E6ED178B8EEBB71BDD62056E30609C84D16BF611CB6D456FC9EDB3D5EDEC6132B757DB24FFD46DD96C6762C2A6B6E548D5EFD5B510003DAFB191803F64D1641BC1D246464935C9641E6B27F73210589C98DEC2C76ACE1D0722D35E333AD903ED41398B57D253FCFD6BF0DFBC47F448339AD805D31D117EA82209E74F1CB840B7D9F5F5C55C735C1591085117A0E83F19804CBCE3D0BA73E5AE87B50804398899A34DD32E859C546BFF71B32DDBA1A1D2F1E58F75946D3F369FDC303E294A0926413A3C9BE63700CF89866B72B442FBF4FF9C5864D949FFECB4EB2A73315A3EA61E9D6E61041819AF06131C40B2D9097DA6DDA5C45ADD1DB5363B61448E48216D8A9C50FD1464353B8356A0EF5689BBEB4F475AD703E8B164237CD904D8096AA753DA37527F27154AFFA9C7859600C6B4764E01E5B2B4E7947A1433A2A0D8C9EB2CA0629646C3E24322728B1D41E2F3194FC14274A204C031353C09A71A2003BF18E5659FE623674BEB3BF766671905AB6251BEFFA1B4756C12DD43371696B62C07E31464AD8197844A6C5F0BDB5AB13937C6810896CAD5E606C3408FDB1A4F04E19AEE1C5BD68369EEFD0DEA288D33338E78D7F9783215D5A6042F64379923573D60C85012706E578569CF07B14E6A48E823C9CBA2D54452082BDC5EB5FD11BDD769C4DFCDB06955CAB1559F95EB5B0F52178F5A31D59548DDF0BA0F3A617E865FC8DFA8C90AC15ED1FFC7869D119E2BADCB0582A88447ABCE80973ADED9DEB2DFB6E9CCC63341F54C0583966797026BD11F61D5051CD526DAFECA49B06AEE6EF2CAB3393A22A4E095CAA967327F5E57EA09B31681F0A6C02C18A171C3ECB13937C6810896CAD5E606C3408FDB1AE7A7A7C9041588772C3789671A075C6E75DA896840452C98BD8754B7BEBDBBFD2C9457BDB274F6010C265A366C7A1D105B0F52178F5A31D59548DDF0BA0F3A61DD80F93EFE8261CEF47DEF66072ADFA0C5035AE2DA56D416D9BFDF8F82FCCE1E164AB97D42603A7A0719187406FD3216FC53101E213F9AC47327637241C978475AE512BAB58FFDC1B61B363D361C03DA2A7ADE6057A013DDEE663F903D5B25874ABD7DFE15B25A944931B8A48D335677E7DE8ADD1A3BDFB07E9B4C8A71F786DE5B0F52178F5A31D59548DDF0BA0F3A616C93BF1A92B7478876BD48267CE8EC1E5B0F52178F5A31D59548DDF0BA0F3A61CC137901241434AC46AAD19EDF470B3971331C29645F2E7C637DDC7EB28864354ABD7DFE15B25A944931B8A48D33567743C32FC557519ABC4C8C5C90F258A7F90897D32AEC1EB91BE453987BFB0D96ADE180E52CF4549D0752C27EF3E5ED492F3CFE1848B1019E4C80F376242A11765638B22524E619EE4005C4FE4C0D6571FA49692E89D41587B4604352C9B4C0717CF3DA6677831B83EC31BACC85D19F66BD498C34808AC02AEC8033B95A40F7890ECD450BF13F9DCC6EA215EB0A167A98D7411035971DF9F4FDA3DB14593DC3F9A27C474C9D5815A0FFB575D7779B9F295B351F40544A4C66C524961B3C3E7AF0C24D2E75ADFA99E4765985112CB45160C990DF84F86DB775A51C0C20EC935519727ABBF5B20C57306C768DFDB524987F4234C1A78416F176C1FC6ED2DE39575A079144EC82A0278020A4834972034A9EEE72F6795DECC1A76CB2FF432D4DD66B25A58933850E097D8BD741426BC67EF0B84153C8E0A557599FA5D44019A311763988A7C37E73922A0757471BEF52B8C0FE587B6B116070E137B7C3F444FBA96F8942588CA53E29954EC6A18F24D0AE3D50B33125E4FEA5B0F1973752CC1E0BB8156F3CA33EFFF18D377E83C0655D33C435895AFD46EEAA55EC0BE894E9567B47D7D2DE8A816EB20A431EC61B1AA311BE8F2B1C0E8135E3A422E7D3372AF62B79E2F1EF75954DC101F1BF2E87D106AEA2092C4B311A95C519012D27C5004BA1E09102A7F0F7DDA87844833D947F991E1561BE22B480A097570A57544216A50917ED3A77B2BBA3140B7EC3EE4A03031CDBDA0DDF90083D988475BBF4F76B109E83D313644E33B2E5B76B98D9D9838AAED6ADAAA8B9C747F48092B5C7BF97CE9B9E7F4FA0C5857076FA21470F1E2233C69D43EC7D1BD9FB1C541DB5C9148BD3D164647232C5F004BEEFB0BA3F1B00128A434B1815147BD00A61822348EB3E3FB1083EC7BDD459CAACD236016DF3B69CDD5561B30121FDF3F8D4FC0B09711ADD854BF42A2BC64329D4E0DC1E1AF326C81A6FB8EE83A4746731CFA14B885D1376AC92EC184D62697CBBCD79D4130FFA13B0E2AC8C5781490FD0A990FAFE6DCDE96C0D279AE47BEA96FED2C4BF8821CFB03FEED5498C34808AC02AEC8033B95A40F7890ECD450BF13F9DCC6EA215EB0A167A98D7FF49DB02A17E7977BEBF2FCCEB999D7FDD80F93EFE8261CEF47DEF66072ADFA0892F05AB9C52EF597BA187677A8C8F8B1A44CDFE00EE3C48E87B61BC74F975E43BAA356C7C13F38D35B4E4FA53E6D37A4910916848DAF5D8F3CC1662D330D1E8D2AF06983C79B7D467C3AD941229E9D8E2583BEE800C9D0C1C4F74697CF6BFC2F2C4DAE3B7CB2966A56D1DE064B0CE3FAF4E779C6E735887E27F6A31BA82C53E4ABD7DFE15B25A944931B8A48D33567709A1B3821FF0C4C61A08C634D48DD040A04031707A3E82175A95E6D68E4B424DBF1586B714E432F5654A760846B0DF596ED6905F4DFF281D9607AEC42AF8E3F2B8F339A0FF7C003EADD0F46D58D80D56228969748593DF6E05A1B6C03CC3E91BD72D8F820785B5A457B2BF44480E74A59A387A77E23C212A2EEA5189A3C565D3C737C11B24F26A0FBC84F2CD94EEC34CC4BE08034AD58EFE1535FD6F32A1EAB77B9C68D417D237A2EA62C0A170470A3133C3511C6D238D1FED5FFDFB745B78963177CEF8FE908D4B42D9326673B22576A1DF589D8A78921D1C2A8A89C6F4942F68FCECD4AA7B0DF998934B7EE5B6072536A468566A60572174C563F215DA9FA450D5757C3C87424C73B63AFBC4C6AC50106F71F9BCB94E5DD2E7590F915EEBF5EA0D81DB8CB15B9EF5A5C221C0AF2847945CF25F939FE9BA9311BF3CF89BB32142ADC618F8B5C37B678AD7D3D95AD6A220EEE3F696EF784CD6E0C2A6E5E46487D2AF06983C79B7D467C3AD941229E9D8BA4167D00D2B2F03E2A24DB16DEBF145124542D7F69C51864391AA980B17C7927D34476364808BC45A0C842A49A7AB7B1D7A1B62F36D79F1A6B8915F176D9FA8E162B662B9CD0FF9203AB4086902DE90EEB37E936F856657FB7A04B84507B692DD80F93EFE8261CEF47DEF66072ADFA07EE7969AE7683C92AADF892326662AAA6ABED20462DE540B6CF0A7D8F4DDE089AFC3F7B8FE713764C127E13859A80668A3A7263672D76B941900C1345BBE3448C9232D1858CEE18B956E46EA9FB7B16ED23C3D577E3B396689553316A161A822D7EE69FB365139BEFF4C17634D729B6EDB4FD3FB0572A7FAE7814459975A0726209B859875385DB62E5E84B45BDADEDCFFBDD2498226587AD0A97E0379B6FEC7BBA9106D82F166A6D3E8FAFE3B3B1F7E3A12C32DE46CDC9F3B761CB440FCC336B997A1BD08E7FB34C44B98BEEED7B7958EC14FB29ED98D953151E362F47260C2CD04BE2ED2D9CD563FBF5C070669743EFF3B168AEEDE001ABE4BB9D6230E86780814713C95889D42144740EE33D521ABF3682F499A5CC231E09CB5482E3EB3226551767B1DD7A899E1C47E616DBAC4729FE1AF9001A123F6A2187999144D6CF17A6B7C986B025BFB1086B5A505088CD61275F17A3D727417F102A4AD2B1F87D79DCE910FC2CD36C575F33143D1907F8530A4A04B3010F9E7D1DF18AC0AAA3B8176C539F0B9EDFB5C0AA1E7CE9F6618E52091CD504B163786BD94349A46B9F58F44AC6276F63C4CFEC6F45665043D7CA2CAEDCD037E43D7B09A547A9B5D2E6A7F666283055A9B5FA04E6A13A8F9F547FE1FC1F809A42DBB7059443C9FB1FBE910E97AFDB841285E1CCA2E9FE974CAF499297045C85D59467FEF392EDBCE5375B7563A923ABDE3F8E93430907BE71187605B0F52178F5A31D59548DDF0BA0F3A61DEAB8101ED96D01E176FA19ADBE613ADD62F17C8D560E8CF2EF0C1C533CBA86AE8F774A4CE3307C4F8065D100712D65FB997A1BD08E7FB34C44B98BEEED7B79550B1204EBC9BB0E030A12488E2F56ABA659326B5351DF401CBC66D55A1F2EBAE37561E7648C56DF095962B8683289E6FB02EBC4B7D30D718B8A4B85677DC618243E7D9F44C8EEE6F036C847C7CA21EA07AF3261856EBF2E6F02C0D3AD6F0C466001168D584F92E641D14308B07515FA67F85B46363E9EA8E795771AD9211F42AB520AAE83ED7A60A34BCCEC6B98EBB05D77BA7CEA2F8D5C69B9DEBA71DEC1018164AB97D42603A7A0719187406FD32169DF703A4136A53466C4EF680EF3B1C3FDD80F93EFE8261CEF47DEF66072ADFA01D156AB733D6965B33EFC0774B4E70B26E68D72DA7B7270F72890003CC526930FB318C02285D8D02E0402BB2211C40B235CE955BF175FC56276D400D15CBFC7E1B2023A8C3C3EE7C781BBB33CF7A256850AC6768F0D1F5CC8BA97DB6270D4BCFC9EB2CA0629646C3E24322728B1D41E27F5BB1D5B7F00F03E1C290B2883F165419914B95BCAC91FCE2F6D67C561F0F21C700E3C74FCC167FD790ED747253F13EB63CBE5FE6AE782BBE6165BD294CFD06944FC1A4C5CC3E0DB9A8481485D8528690D9FD59E32749CB68BC1CCEE6DC672CB2D9B9380698F04661E0A278DE308BB3A62C33A68F66ED09E95D7ED37EA51212C761FF39FF07CA1074E4EF94378D6E62DFE08468FD6B20B7DB0D368210F5F48C0943E4C35E89390AF250169D3CB0F2CA00AD7E738BFC7889C83804EB7685B3453BAA356C7C13F38D35B4E4FA53E6D37A9F62C5892688B3F6DA6C72C17D442F4A0BAE48F3E792CB1B210022B0719F4A130211BBA8E2F26F6C29F352B6063A0E31942D0CB0FFFEB58844CC0BBAA24F871359ADFDC741F537AD656F04659791C4961C1C8B10A1A1AAC92F8705BE1E544EB85B0F52178F5A31D59548DDF0BA0F3A613FE694CB63C78984437C15F82DE65D85DD74B5E0F7AB512BCECEF0AFB9F587468C722F2C94DBC7631BBDE2D3C85C9AF0F38284F4C50AFEFCA3B594E2A5A106D3EA06716A8E450B953AAE90CD83DFA63C5B0F52178F5A31D59548DDF0BA0F3A61D53E381CF1442E2748DC2AC2919D3C53B6B9D234B01046454C6F53AD92A243372AF030E83B497BA576DA6767AAB2428273DDEAC46653026CB5E9C641151702AE00E8174E841C88EE28F353C2604FA7B70FC0C44D60350AFB7999DE88624185E923276034DC7796253D4560A0F841DFDB016BD3CDD13D6561CE0A69E415CD30CEBBA9106D82F166A6D3E8FAFE3B3B1F7E3A12C32DE46CDC9F3B761CB440FCC3365B0F52178F5A31D59548DDF0BA0F3A610E3543CD4840ADA8B7896603E2783D39E928D9919BB223FF7DC2EED56A9EB6A924E91523DF0B71F56337F1C61E2D9D9120D48C6CA5594F713B704535183807880DB60ED2FEA32964A78D91D26C505813512DCE47F9C39BFA579529609120E762A7DBE5ACD3E4E7547C51FC3C5D1F52D9EDEE6DF859F96B4C3DB8C6385DA0A4FD5B0F52178F5A31D59548DDF0BA0F3A615D0F434D5B36C0201402A9550A730D3DB1F9A78D34ECFC7733AAC4033A4494977105CFEF8BDAA379F7CD88457C5DCCADCD95DCF427051F37A01A4824913869054ABD7DFE15B25A944931B8A48D335677D0B184973D766720CC921BD9D3AD7DA0124542D7F69C51864391AA980B17C7927D34476364808BC45A0C842A49A7AB7B4ABD7DFE15B25A944931B8A48D335677C317E3E5A8F0A31EC1E20336EBCDF1E07A3084ABD06F2F799616BAA890461B111D5E409BE3720F51CE50674C5CE75F64648B420BD31B9B71507A1E4A2ABEB6E250FF55DB3711AE9BF962E7BA41C8739ED3F1FB96C62347341AC1807F45DEBA1960100825F3142BC9CB23C5DE6D5CC5D478E9D2491C6C1C9A414E5D6175D5FA0E5B0F52178F5A31D59548DDF0BA0F3A6126F652A1C2E8594F22872DD443DC84E84441A36CA09AD779FF85E85181DA9DE8BC50398EFDE8C90487488002BE1105690CE3EC5C6632E98CAB4ED73AFD7FAFEC3CFE1848B1019E4C80F376242A117656EE383AF12A2A70F0C38E9D2298FDF98536E3B295652F30153A37428C4C49218C9F05240782EBD0B97AF4ACF8233FF366B520AAE83ED7A60A34BCCEC6B98EBB05D77BA7CEA2F8D5C69B9DEBA71DEC101818C17CC66C403E2C1C212035EEF9901F195CDDD775E02245891B2011E38AC3B8E7F5DB7A1EEE624B145AAA974A76D2D6DACB16F00DB95E55939EB81597017B0134446856DCD03B2DAA5A26951E69B3AF3C8D6641EA16EC1CD7AB03C4BB6B4A1D3265F59DB1591ED51E61DB5A5D1A2F87553EADA174C3540E2D9540D4EC66D04A80D00F46646D66B3A859B159D6A50D4B5A19B45AA6353DD06BF85606A78093743DE1513AC19E8F612180371AC979C2FB02EBA99FF4153DE80E589AE2442695EDFB0C312C53D166EC2AE1D8CAF351C149AD49829054A899C200C92EB6BA747CD1103209767A86A7032AB168C2DFC59C784140E825A57EFD37501B2D29BB397A2F45DEEA614FDEA1436CDCBB5D2627175F50F1D9B7DBD8DAF7F63D3979C20528E6EC12D51F057B0C5DFF73450CA1F0A24DDC54DDD2F3B9E32019C0A5AFBB831FF99C0E0458E86D8F42D25B9F881D631C6370D0D3E59F522F6656170AE14F9F8E6DAAB9C88DFE07A6F61FACAC3EEA42A392210F06AA6CB0356254D374C28452C62542C211FC4BC31B47E5882266AD153BD7AB2265DB85D57320BBF6D59C3BD29AC4B744EB2E7D627D1806DD47477E332615693AFF192BDDAE8B775F702EACC0FAC789F6487FF9A4253BF23CAB5F7DA582E62A096C0BFBFAE46800601113BE6D19B2935E022CA71446B64094F75EA08B440982CF95BDED70FDB019C97A1B39208473FB42515FA65673E3FE7F491A73F8C112178F0942C96A4EA7B5E30FD87C11180977491AF3721A13D83890A3ADE53D753D8DD104A536A2E182965645EE362837DD1AE5F727EB45348AC939204DAC4A68E126E71E33E592CD0BD4EBF2D8331A4BBBBCFDF824206EC00D213B42C85ABDD8DAB8BDCCF2EBCE33CC9C8D20DB219A7D7CE3B57E9ADF82F20CBF65F1713D2D8D8413229567ADCD6406C402E09CE512D7C2EA5805BFDB335751A2DCBA8A00E57FA88356272C378DEBC61830C677BBA90B47361F0B0C25BD974685501B1A9F65F712006417C43123F4A48034654A69865091B79DDC82844A17CD1007CAECBA47AE34C3C682B02F5A766FA34248F7988CC0D24AC68D8565FD52F468A43D2EE000EE4192EA47D306588E0C36A568EA7A0752BF2AAE151EF528ABC3AC39CF9B6AE7A5B5DC017FE207C6B033BE57E3F321B1EF0173C7577A73C475CAF3D792E9C47E6533C7F6C5F0CB06C7CBB52EB31405E70231824F7FC0F9F64EA32802F114CF8A6B27DBE6C260201DAB6278A8FA05452F2FB0E60B1B527936DBC64F83D2A4DB65E5209D02A3C1EE4EC8B86E26852F0106D38933E3D862CA185771DE79AC31EB8034C0CDF9EA0163DB4EED20344B99E1DA0D47801D9849760DEC4BFEA8B771C5E102C66564BAC5534C7D1A43D47A7A17C7325BE732D70177BA8D4FC6232D0D6E5598C01BB493054E8F288D30D0FFD54E1B22EA4336D8F6599164F75B1D20CFE7E477EB5AA83E427D5407FDAA25349981AE48D2D3BE8707BD6FABDB620E9CF031B88FCB74F8A9723C70A401584D939F99F44DB4EDE558C86E827C8FF63E55376903651147E33BA5C0972A666B6CCE1B9C62DAA84252A1E9F880CE89946E9439B6D4B60972CCFD3E5624236858DFB874E3F53557A30AB3FB6EA7243B9B1EFCEC35EA4617D8B42BA54408832AED90683E4E22758A915D0EBB5223982F805F955FC68C2EAFDE2DD99E13A8D9E37B531053E980D81E3CB5E995D67F44398FA853E179D953E21036260B8D514379AB95625B447A42502E2D8AFC990314B504BD4E3413321686ADEA7FFE5864F8683291744A79D8003C961E701BA8DE060AED2DE23FA32C8475C3AEEC0014CF5ECB401463E4A47F06C5EC63309F1F57A2F1699D00B75525722E8BF451297D27AEEAB76782385F1E0A95051D543B4807D417E19AD2F332FFAA57F6727B801AF8F0487CA111FFC07C81F96F911AD1E75916CE6D37EEE631A6A2D8D585346703B261917C7DCFA178E55F45ECCEF116246AAF05E4A6F0527AE4FBCCDABE4287F73FB46B05849D920ADC00E611A7BF6CC4A65F1FB371ED68862CE0964DD44E81AB64EEADC571EBBD5225BE78DFFC5B65EC3B62BB55493AA0FB8796B0EE28D884F8C0E6B2DD2327B5F62D6615A28F8E2393FA185A982C15F679439B99E981BFD99A66CAEAC46FFDF2A665AE537BE34DCD020DC6C994E7CF310A57F807E209AC156A16318E2DF9B9E7114602CBC749CF5D0DA747B22B176DCA1546B774DC2785FE38C1B182BF5438807EA41B8E31159967D4C926F50F359569F521BBF17A42DE6E749617458AC223F5DFECD40D384CB447381F945D16D38E55F329FB9FB06AAD61D1F57B8BE021897CB9D539ABA6C5453FF323B5D8B26D47FA061DBD6098256F5669DB566717C2457AADB8BC487A085B5DCB1A87C2C25D743EF44FB174B66B6675F14C77FDB9B28FBAD23BF3B0DB0991F1FA1BB343063A9E8A961D3D4E47CB4C41F1CE18C4097BB71A4193186B76694A4C1D67825D2FD826D1D00711B21E51F147883BC33C19ED427878ADBDAC3BC7F59BB0E0056BAAD24E35D9C523587C235EF7E399CBDDA77D10F05F7F1C9FD34957EEB30DB6BA17BCC7DE0983C89B9AC539394740355437537666A77413C0A1F2E4B2257D66BBF948B6C3D88095AA3A2E1B3EE4A0834132ECF15756C5F19AD45059AFF07B43C3B307083AF349A1CD2048D52E2E74A0715ED7074FF74066CA5274FD226D29E8F9A5BE22CD317772FD0AE65CF74A6F671C5064D91FD3145A752DBDFA26C53521585345F5A31A1AFBF31AC2DB702F28FACA51FCD577FEC7397B2405400057B44C5A0512785377B081C75F12EFD67EF3739BF7C53D736E4CB13CE5D58EAB0A5D575588A32CBEB301BB516021DFF09E8D16EDC2E3CA5F7A766DE5AF412867F65786CBBACE0551E98A25A3ACC07EB1A3E2A08E337F72BCBFDC18225ACCE32AF7F266818DA10BBCE85BC042A76BCF5481DCEDBC9BD13F0986086EB0E741CBA5116401AA08336F73B5AAE77758A72601A03CD94600197726825C838B3B9F2045AD2D5342ED9380FC714B9F5FE9C45CE9393BDE2B3CC0FD3D77F16557BA60535432ADB5E8791C495B60A45EC042378DBF3992BD3E40AAA8BF66EA9ECF735EB67B1B2A5A5CA2CEDBE06068423D62D572255CFFD3D01A235DA5A5BDC2EC1449B3B9F3FF232CB09D384358DA197FFDB27ACA8D6003C2C261108823F383FE3DFD4EC0E295AAFE4DF8537EE883B3513AB6AF4C4AFD6C05A12EDA51C92B8FC466B478FC9B31A6C4E3B541C99881EB248DC13E6E8751B46D96ECE34F40EEB449014CD59074FFBFCEFF66591C52E4F6B04535C2F134B1197B99869C8030DFD15D84B7CAD57DF7EE134C91C3B6AA5454185348DA517A3BDAC735B33F0D2A7DE032373E52D5FC0AF626B882BAB7F2EF093DBC776E1822A7CE2EE6639B9A2F833DDBBB629237B29A2E935004D215C51D025042F886DBC5077A029B095214E8FC7854670B3600743D1F1B3594F047AC77048A1C1B2668B59C67AE95D567707C5EDC3EFC4866879E12EDF53D29BF1C183D84CADAE03318FA8277C5816658F6B425AF427C75B754EF9C38907C74EAF44912A9BE463A4D4E6458CDFFD8ED6763F25C3D9590622D4E793023EA06337F0AD985431463FFDEDFE446B26929B4A6530781BA584532E4C2BA14627C9F0B7CCE3150B4F5851E10D5F3FA9F6A42E03146A1A10A627DD92A2444C17D9BDE40E8ADC6BBE617BBB0996D315CF43AD16CB64B8FA24F1E07A0E4CCE6A1300EE436B8E3EF3279EFD142A75F131FA3279512C6ABC0F28D84A1B2C0EDEC6FFCFEAC19F5F6C94E2528883E4AF3EDF3A297E0235F47F18A17EAD1051800652B767C4BF0AFD56FBA6428B7217E764F435FEF41D7A3B621E20E0CF69221337BCAC379E44FE43FD00DD5CA5908A0B9FBDAE01783672E29CBBD1B7F276144DBA9B8B6129520B693808A9E7C76A68FFD111931284C77F0AB8418D55F91ACBA03F44593856C77C7F473417F250A2FEAAAC16D259EADB31D27171440407949B1F2912A6CAF58F9955F8FE99713491092B9479AE850A2EC7B7C5A130EE9B23A1AC56D2BEDF632B75D3424A01CF1FACC903C744212D93F044E22019106C0C662726C52DC92C8ADE5D9BA91B58F5439751ABC638E65D6939DD8ED65A947DF54BD35E4C3CD188B6288390B1421BCC92661703DA704AF78C05DC054176B9A115614525D84A05411C44B183FEBD7A860CDC09467F8E409134681460FD45FFF21A4EF4716D1546284BF8AC32F96899D76E391F3050D6643C1C32EE49BB4D0CE850A246D585032D58F9A677A614E98614AA53B7356C5B4044057ECEC7A8AAAC312676257C3B86498298E665E2EC2DF97BAB727273E63545EEE701E02035CD63253DACF7CBC08B27690D8F85A64E72076517832EA5D2B3939F118050D89A7B17AD464A615AD1459106D48EB3C2BEAD6D9BBEB1044FF296763CF5519C19BC5AD8A6E808B80BC0C14DE982A7100C77CBD08AA57E6ECC2363969FA0D03C0A70334E0D891EFED98A1B935D0ABC4ADAF5382F630796250C7AB6ED5C653A9DBE7770955BF3A03A473EC1224AF8ECA0ABF92FF07A7A8C4E91DF8684C96CA5FA6C528F61D1D5E3C2E74CE982B0C18C241CF6E18A049B477FA52E6BEE354F79CD6FB8EBCE876E01FFC8A72777D558CA88E2E3D376B7788F254BFA1672F8DEC36E35037FDB72E4761E0814C02F59098DA1976B4EF18C3C95DA30BB36C14CDFC9DD1C9775C0CC6A80CACB777271438829F4F6F87BEE68D48A875EAEB2207DC849A60BD036DD4A7EDCECAEEF5F06743754BD166F12DE4CAE05A669E5A5153E90A0448935E2C692C4485E78E6E5A73D764405812551089C87C36492A2E34738F895FD4D57DAF324F563B69DE5F373F4F723434B605FDC221B491621D0214FB9512BD584203C29DDA800DD08F107160F53659D8B755F2FC49F1FA8B2C47283985A5260BF622052D0B7920EF23F7776CC1E7D3118D07867C0BD20CA80A60D928EF0D64268F1DB2FEF8DB116D65F0B1EE7DB6D66608EAE6B9D573C964D0F69ED8674A4AA1C567D8EAE3EBC53DA2B7369E349F36EF7C4DD34AEA701F3C876FA314706C6ECD371B106CB1F1BE02483F9AC50CC8BCE7E39FF84510BFCF5A4DA44399E86EF902F3DDE79C67AF35F3BC3934AAF510307AD8B6CFF9FF5B63235D57F8903B98DA013C741C3428B56C046739B6CC0EFA0C03C5E4953D50D26C12E8E62E6F13C6639FA949723FDB6D56FCEF39FCE897D7102A8C43BFCCA4C258152B325D1EC0A59334089F7BD63F15C5BEB99068B240D7E5FE892F0597B4732C94A14B39C3C435A01D31AD8311E857FF8C47C576ED7BEB030A0264A67CBDE7C2211CE2B5CD736C6B656F314A70ED909ABC4E1C32E1B0A09827166B4E2E8835539C3EB777F63A9360066962637D660173C2BA9451FE2AF3F6F7FFF5AFF7EFE6F41D157776078119E375ED5D6C73711E3B9B387ECD8A06570AA6B6C0EDAB12775763250EC72AE936570950851D7EF303CA26EB17D55E55CAD97CD00109E80DB720971C9A8EFF7767CEBC81C68003F5282A8DAD68536831342E75C3A03CBBF48E22EDE3755F34F059B15F879A35F757505FBF08AD8655392B0D8E539F4C53DB9CCFE8138FC268F42AF408E3185FF07E8F61B1EAA6FA46924A16E65551913911C0C705D26658FF42227DF851A7404C3A0082BAC3F0504C8E8254EFEBF046C7508EECF2183430985F381F9A39FE531482A728683BD221182415FFA1E9AFB70D6708B511325BC21C623AC530E45E514F5F389CDC32CD0D2A65FB01E39AE339519D3848A47192D5BEC78E5881795B2C18037703D79A2EAB9BE5BB06474F23ADBDD42171E899BED9EC44ACCD96719262DC787F6C4CFDFA6284207502C12152DC25FA060E7C2BC90A55228C26DA74A94DD69E1DA78B97B7E72CE22D07EA33EB83FBA0F1BDC65AFC4559C9D7A4B826657FF22AA584BE89DEBE40E4FC69489A16BD98842F27E7CED00E5C7864673FA3383B5FD38353230AD205519AFECBB4EF009CB6EEAA912E7E8A73D6F0EA9E1AC743CA050EBA10115E5A1FFCF3F27E072F98134776A0D3F0BED9667BCABD9E68EB6BF4F46270833D34C4A875E1F17C4CA0F8B6615B2DBE9B2FCF1252E2A528BB5F5B63960AE4B7174C9CBD99ED1665E24446C93C549276A1A48C336D22208A7234FABF3B984574AD550C030D60DD8E2850915871093F6534D60B392667428BFE76AF04A4D34D7737405AD8274A514540925720C873A212F25D63F2B7A181BB6FE266D01000E527C5134994B99F630B81DEC3371E5B1771B745B0F369411EE1BB53422D753168B7F055413C08221EFB76A63CF09CD9167040A8B961065D8F9BD1BB75411CE7DBCE4671D812A603D8A9CF932BD070D966A69923CCB3203343F233AA3FDE52078B17F53ABFC22E73D515A63A3BE56616FC138ADD84D6E2E3AD1F1BE1DF698F8CF4E72B1E3C3ADEADCDA90FD9A2B6C424516AD28DEF9D96BA82B0835E0716B80AE3BF78D7F0B9DAB584C51C540342D89268C316931851EC580C7F6A2AB5BA05F98582E19DBE167B9DEAE57B78DFF7D4F6D322D8BC138DABCC44B4FC97FB514F2F4AD0E3BCC7FB6DD1C08638BBEE1C5AFB722B385CC7EAD522E5D78B9F02F21AA53079B499E70F5D450C58CC9BC4C79624DE65BD4BA8799089A7A32456DEA32393C6753EEE364F81A0196EC18EFAD4E21914A446EAF8CAD124F1E2A4EEB54F3B60B7A99D50D9414F488DA8F2F87ABFC79FBBE3F204A6D61870D46B3B2F4DF5ACFE088A6B4D3DD966F8A35954FE1EF07713D6BD849D64366F67711FFBE2217A177F6F28115E82BFEEB6F2F007083BB2B75A2D72526A9DAF638A94B714E4DF066744CE1619D977E20F1E490FDFD2E3976F650DC58D5D7B1052D31F35B95D7ABBE7DCD59B876AC99F0D162ABD467EDE78ADFFEA4D1ACE20E949641520FE75D5C1CF14EC21067A2B27DA8F989BD0ADD15047886AC273C7DAB8C1BA563346EE26009667414631E71B3564AAC840847A22DBAC0DA87A208CC81CC22D2E0032F62D62AB77E2299C2CB44DC9761067A9C083D4292907919C85F0E8EC9394497F2B9965C1455C0091D3AB8146A4D0664C5B24D0DC5F8FD23DEC1BF7D6D6203693D3C8F447B754C9CCDBE957863F534F69D4A1365A5A18648442CD5A53322EC1AF72287ABD92FD82B1510FD84017C0496C0C643D4E457C2FE492E2FE3F4D7A16389078FC93737B8A97D5046FC941EA9D291752DEF205A17A9761573F9FDFE232EDB3F60292A8AC3E23D873DC1A88C0712DEDD80265575AA92AF1AE787EEF161CE164B5B9DF9D7A2AF8AC605BDEEF0C11E4345C3823E86B63B7CE5D7A4B88A2E2346FD9FCA6FD90BC83E536F2765FE3A625CB4F147C834700044CF2DB7872EC8884F808FDCEE5D1D6748FE545E7ED3D8E473C4BC2EAFD4216BB7C5038072334B4F63526903802EDEFBB056B0FB76A768D785CC4CA29A206E32961ABFE55ABD5BB0DB605004F2B364B09EB48B68962F13512533EADC6FFC65EE25535426332F928D8C30499C51624825DCFE28DCC31BB6A68FBB22CD4F0967BA1B361C081AA1E9B73E8FCA6610445861BD3F0B37DC3BBB19A36E726D46207F3FAA4F1708049055926633A441FD9E624642E4586812986615477D6FCEFBD1EBB5D0E052918836CA5DFBF1AD147AD9AC297318F74F22E07F3157C4B7DD311A2F3F93D66E335BF5E2F78BC1BC8F4967C92467889D76226F5E92A6177906E7D6ECA48692AA3CD5358970E54719886BCC1C394601E8D4F439E3B8C01EC73AE2DDC576DFB57C5F5BE1A5C52257461E9F17056878B49DD4723F16FB3A9F8624E5F5A4DDAF0847E41F815A8817CBB42D606BE9A184B4059D77EE30C64DFF6A8F27A7FD2E878B70D9BA63C5398BDAFA5A3B1FC2BCBA6EF9051E12936C7B3647B2E1C48FEBF6A7CA1287472F0F4F5A274D0266B275943DD48E1FBBFB41A967DB119C1DBB9B99BB1D93B2BF55CCCF83FD17B8DBA7D1BEFF995D67ABABD7FF4B51477E651FD8E1EE7E650C6E160E8E3184F9AFA3CD2B7D293D25D831C6518F40B264849C74226EA8048C79F786379BFBF1BF97384FE6DD2324924DE2678FE5A4036F45E0B813FDAF968A523817F921AF4C94B6611C04E41BE91ACDE367FEF119742B0322AC0516A1C270E2D7831FED91776F1904C81877B74D93BFA6051F1FAD2C303A37A1B4611FDC1E57F96075B37AE6A5295BE842161115052BFECC8E9B69266455C914994822423BAD5791EDDDF4C81C05FC7458AFE17C4F6B5FC9E9A7659500F582593A34525D56D5C3966EDF25BEB2A4B0E54440643705C02E6B96381E4A21E8DD797443A5F4BCE60D31191FC6372921C2C6815562B8E7B81AE1A827A1AE2FFFC6BA7CB9F61399A91F37101C1DB157FBAEF6F20A569C2BE79608D2E426DF0929E4B9ABC8019BAA5F276B83FE05F923D3CDD9B45B229151B20E5FC011A6254B8DCA42CED3198C4B453D1C43B386106F40007C05047DC1884719D07BD9729ABE87B0B847D95845AA31AD177124EBAD08E5A935801862A7413F1241C7FCB5C24E3D204A6B982E6D86198552597C9E35CAD46CD668AA4087CDE901C6DEB630E92FBA1DBF06B5415AA776BE410400FEF562D86267ECEE07106981614EE78FDD3342E1003DB418546FA84AA682A2BCF2001B3F4D5D94707A4B4600141BFDDBE6BA9D704F331EDBE9BE3486BC5C3FDF94BEE51099989F10F08115E29E6DC8C2C6F9C06278CF8550B8E0AD0BA79BB6ADBF3BF11A883E41B54BD588298F9EE03ACE70CA38E9FAD11A403D143A34534F266CED15D32C85509D5394689D715A66305A26231E2860157B479B36AC47138EA96A75ADBDB01D115B820B310DD013B81C0CB7E2553CD2694DEC474DB5A468C260E5C21A9C2311414354F5810E6E34867D9129787E4C64AED7EC64CC556D16CA6C96C2B4264C5ED6ADE8461AF305F40793978DA2F99178EF33D7D7599423E1161D0F0959A6B5CE7248462D9A16E15C6CA67CFA9DE9D977D8FF9B24C52F991077E34DEC41767D6FE22A5B5D9DDC0DD2CAF294FB3CCE958652B6250E2A8EE1319158B38B21252B467DD5522E2D7E68F9EB94169794DD7C514A29CEEE2FF507937F62EE8FB90BCA1B911D1BA06EA1C8A1AAF598C0C81388E4FD0D2310F4AB98C56987B620F97853B02AEDC3F2CF3081D2674862D754F96D0E1FAD2796C3310D84AB76D512403BFDE5C8141C5660E2FF42D2E89DD99D3C364017C031B917694122792D91443DA5C556C2D927C53664D63B17C8EC8C63D8B45CA3D74D0B7CD9B57D7DBC591D86F001DE976764410EEBB57151C31887490DDA396B81C49B5203FA8BE424B36770A361648DE5610D24AD85FF0E8BFA76A48BDADA9D99ED220EB1F190D56A41DB7CA1684C55F9FDED8F2FD672998571954B9ED81DB3C8CD5E71DAFF453E87EBA89F3BAD615505592B4C2EAFBD5D912DD8FBFEAD94F200805064160A34111AA2C43FBE66E973D27D5CC3E0F2035EAEF6B186AC52A2512CAF788071FDEF03E348B42EBEC6263896928E498280F58B99083CA3B10A19DCD283EC94D74EA3FC2CD37AB5A4983914ECD4DDC2DC80AB8FA6A95C945A7CCE4885367939085C9E97965B160635723C2A6EBD15852CCB84763BFE22E0D87202024A824BEE0E9E164FAA0D0F473324B2597486B9E27C010C90C5D113163B0A9CF2B29C909CE0951850424BE2DD4CD21B502536C462A55ABB4A3153D0A86B7232B8CA0DA55443F1DF4BC9240F80DD34789176421AE067E556346296FCCFE47DDA106BDE6E469C9B7B88285B4376EBE4BD777C93DC16858B8C1AE51D9BB8C8603D66570B7F63885FE41A03FD0C14B908A83F8A463CB38D3E02468966F1D62A9AA76063F627E72659C0593F76212BA283BF65B84A100943B08AE7AC6BB1A718EA2D17DBE0C2C387FC43ECF7C60BABAE526EF7BAF7C3AF1DA32909AF9E575359219A96FDA6533462689C2D177D4A9C2BCBB23603387D55C70333098C529FF92ECF72E525CF43E24FDFDBD1E909EF188DF48906B2145472AF71B461FB2A7132D5CF6FAD6E109FB1A7A48F966B0CAEB6242351F6367AA96AA4C71F50DF33FAB9669CED4FC01AC733E16B46F6FA303183784F8AA9C61E679C7EC09CCC29A5BFBCB671630E14DC60D467F0C05EDD74D307FBA09CFE3B2114E9263F50DE50309BA45156D428A72B7F49DC4168CBF72D41686D6A3F4943917F46787B879071E6C00BF2160E44EC5505A9DE52862786F7B80C2553200013F3211C3D936D675566AD37148AB96B62CFB40EB928D4385CAFDA3AE87183539DCC366697ED0F04C2FEEE86BDA8D256935CA0DDE2E30D26C91FA92216928B1E2896FF29D8EADE611DD5F21EEA0D6B6F7A57DCCBE56C51A74F61E8FD242917EADD4149290E9ADA2361845C4BCD4814D0245BE4CC17B84F4D6C70ED07C2C579D08B782B6D0D68BF460D3214E320FCF4777F5B21DECDBC2FAF9E0F5087F7A683BED41273C21561F4C2D1D7C7D2053D168899B94EA83AD51BD706956B1D6685BC6317C32C26960980B9FFF3D2131F691D7A70113C23F82F61A4BA74F06068DD609C0D64E38DB0D279693E8131ACCD8F1F185C4EB988067DCB4AB4755030FB552A25E294EA9EDFC2EB29662AADC5172231EFA9F928022023582AADB16A57BB182806D6190997217B1120F1F0425BAB2273C4EE65B666283055A9B5FA04E6A13A8F9F547FEE7DE8ADD1A3BDFB07E9B4C8A71F786DE7CCB74B39FD5F31AD5733F0281B448EF7F8B6F643176623C532348D0923DE10C23C3D9C05BC6D40F3A25A6D0B10456D2E93677C783E525BC5E4D4E72A041A02A65E9A5F32FFB69B9CF3EBE13CF4A0CE9BF05C0BB49675172843C61905D28AE89ADBD2AB587BA15695AB7011B230FE0A5A33DA46A3DE53F838C0D9F98283978A2066A350788D5DF3592E92D87FCBC9799C439E32FE0F467B0C49E8B06661805D117908BE3A2502958E3CF4F31DB1EEA12F93CD0303E9B69479986EC54309FC84831DCF9F71850796E6F02D733E52000DB469D00D8F3C9C77B37BD9626693683D97B4E4D21213EFB93A4C48305063B03C574C76E79AE443CCAE87961970E6FF9AB389C54FC8A3016A273237BC5D45720B7D82651F8A6148A28BB931FFE32D3CFE9FD0C95E1CEB614820857BA3AEA8693CC976AA7AFCDDA684DDFC6C1FD08165159A3A54D1E6C784CE7B1D8EA359F2175EB9AF696EDEE12172448CF3248566FC65731B335F97F81032BB658BC486D9B7D598025E8B45F5C70D00DB2D66465C54D1A16A5C49560622C851308526C0EFDC116205C39C6310B0912C5E179AB6DDDA6721D33F11218C5AC587D038336DDA3CC8325C8E0912AAE814AC734AADD65964A0BABF81F7E98ABAEA8DFF2D080490668C123A5F92425252D9E7FDFFAA91B86A9B6700999DF83469793E5A3955C16555B7FB133E7F6982BD53FD7FB293FC5AF3F89F92317705480A6C8F881FED1CD1FE1622DA6097F302AE13D95D3352461A7BDFCEF892EAEA58D7768C99D675871ADA78A46BB558B34BC7442ADF5E72878F7F39B124FE510167EBD74E95FF1BA1AFC4E71CD98B96987AB1318B1FB5551ED295D6614287156BFD3E153E01688DAB135CE6370064664B8265E604020CE973DB77D2AC4462237371A0893D8A7A3D188A2F226B57E6411B4720474986A7A60F01AE0BBBCCE9BAD9DF6B0580F211AB3919247589A14D4BBF245F5D84D8145B20C31B030C491B8814007DA2ADD59E84FF5FFE027E54A683C509C8A9A5F8B3527D2AD6A5EDAAE349041A369AFCB7DE463A668C8F6D4CCCE7D09770E39E61959B6C21F543B416BF354B802D432F364CD40340BB14B4EEC95F0930D156BB99A47C2F5838FC871387051BD93B1973E375A84090A0279BEB6B476F26C47DE1171A3AE91E77039BFD9BA1EFD79CE655DB6A6ADA3465131D28523C10B0B345E982096EAE1B390587EFBEC4735C5D6B28DD12B45824B13EB2A26D4BCF134A594E46C3E899D94312554DD97D87BAA1D89B7492798FFB9234D2C92BE548C82FABD61F381EB69B97C5C7B1CFB9CD4BDF9B15B6186D4C6C71A53C7AE533F0425773138C8617CA9A49399F33F4C799E2797FFAF07A1710ABA2ED3ADDD848218825634D3FD38DD2F68B6BB3A1F3BDC6312FB890FB3033D028E6621013F7A0E53FD5B21A62D99D39AD3386BC8AD9E4A97D8A7CC6E3E735506ABA84705AAB1E668A63CE3D330E4AE4583926EF3ECC5B9C02DBD11E3948051D7B35E7D0B29DA21655D336D7A24D5E8BD81C12C927B43653AEF54F6C21EC6015D2C440E5175AD2B44F3CD493B853D91790C8887E50175B2D15169D34FED5BD5249F6F4975FF87488126DB51BD212A404373C7959715947E365C911DAE00F81FDE7498C7AA27BEE03B89725E9B9F57AACC33F575E1B6ABC470AE9F089BA2622A0D9D33311D55AEA0BBE4783E95DD5633F2DF8B1A8A8AA5B85A736F51635830A6C72D66FA2D9A7EDEA0E0B114A2E5085025198D3C09E7DD414CC63EB742E7F79A716CF1E86CAE5C7174778343EC56A5B96D9CDD32E2A5F0B072D799B77008C1FE51C06848ABFEFB3ECD360AA6B00F4C16261F1BC713EB0EEF6173E3090FDBE444A2414B259BB93B16163258C1C5905181B09C7229C65080E4E1C54C94E208CF5A96DF2FFB1ADCDD95A76C83DE4CA2CEB066FF2677A46C3FD70DB72C4ED1F8AF78A58AE0DCB7F5BC46B8CDF1C279B7894D4548ACBBA6367B190B9B1ED65048790A8B81A1C18E3D6E16D9BA6A8B435DD6C523034E72F410B5DC600A82AF2A6F9D51FE23A7912D3221D320CD6E557A9B195AFD8AD81ABA2012F3E3BBEB6FC5C2871E53DBD8DCD708092E1BF7C1F85D4A6C759B3F85BD6854EEBB03865AC1A6C5D659E34078BA0FD85FF71BD2F40059B955FFE075B69D875CED443C8A0E16A1D3ED8C21684A2A7BA78A99F00CF3CD1A9362AC16C6B6D8D5489ECD4D0EF02B645901C9A7B93B43D28523C10B0B345E982096EAE1B390587EFBEC4735C5D6B28DD12B45824B13EB2A26D4BCF134A594E46C3E899D94312581488CA1CDECE76006A0DA2BE63059BA0C98D76B2DD92957C6F6C780C25A3DCAEE4E78A5C7F53F79D92329D76D6BAFEEA4579FB9D4E57DE35D4A84CD50C982AF89CBD30512E4C04E9587BB6F8FFCD78D290FDCFFF1F1F7C11E0476175A5200CA59E75EDB8DDAB8D47E372995D6E1AF200648BA22E2D995C79D9FB32FBB0EA94FA66CA231EAA20106C625B77798256EC470F98A78773760038ED39AB71B19D5DB3EFD3B77E206A5B95C4E9CD12C5D5F696B7FC7CFACAF4495982232F8F94B2969F0A774B67FE1CCB5BE470D7C156D0350318FBAAD273FE5AC8DE1AA20F43438B6A3B408DF01072694CEF830025623E304AF3B62E1C48120E144407E7221035D32F7BFD5E3508455538DA1D12E0EB2344BD5DAC76110ED53961A65AD381BC365EFC785EEF542B91B40C685DE0A0580AA9A7394FE39D1DA3D0CFB207875F4408E851EE361BEBD533627DDF4657B10FCD25737B608E27B0C2D70924E596AAFA5596C2165C1CF2CF536A2C071CDFFF3A1F44CE51861294690272B9D7829A99A9C3C918AE2BA194EC567F088AF2948A2DC2A3EEFB95D3B2D7EECFE96C14087A55A3C21234D35F7606016CA79CD65A767E42646C31D91786A3F6A6073DA31393C64529453B930010D0731087F99DA4228D626D2789E371A9812F12397F35A9BD01759AA533DDC1198E07FC8FB00DF6CD9D7AFA85086FDC9515CA5CE5C1FF2411585C15CA3B03C4E7EA3B3276EC6768DA77F460E5489265C3C023DA7B3C992FE08F90CA38C4F6C058B09BFC3EBAD4689D0BB5FC5EF395BD8204C8447D3B993A137B0A05E9800F97CC7AA290D4D519EF8D7221B7D44850714142BFCFBC2EA44D35E942524C981763076086D3C457745B5F4A73D6740B8F7AA92CCB5A5809DC411B50FF0E7E3DA8775BEC7CD683F4FCEB2300D09265E5387E67EC193B8D4DCB33C5A0F89575B9E54DDC49845A38F4BCE0125EF1AF735C38448C9C4FAB3D92F80137094A7B0F92BE205C6BBBC9816E1E9BB1E6B500AA377A91EE3FAE7CD4ADBE13AEAC7101F65AB03920B471C451904C8B6BFE41FD5EF395BD8204C8447D3B993A137B0A05E9800F97CC7AA290D4D519EF8D7221B7D46A0B1C2B89D0CC160D61784E98A2C1AC981763076086D3C457745B5F4A73D67185327668E388C1CFA1F5E9B5605FF3A4555E75EBC3ACC2034F97F17D7972692D5DAEDB47CD4E91B3E34E055CEED26A6633D0F0A1CA9D3081B65AED250C648128B299FD97AFED5087B52DC541C38D5556713333168845DEC8BA4B19DA49857904FCE7E3776D73CFBAE75F584289BBEA2179B9F21B46D1088AE2E36E2C7AF474BE103B591DB11D01EDD54B71527C661A7084AA9098E7F9134D256791F9FC5F649C8CAA30A2A640D63975FE3031F6092666D05981C85415ADF569AF793F147AD7DD2C54EC1245BCC2BF127D2BB95B1694FBCEC3FEE1CFF277FA034FB3398ECA4329447E00D6286DA0645CE08319CF8C83C595BEBD034FAF7B37C04CEC3DDB8BD74EB3ABCD78425C0518B004D1B650DE65E64AC1315B983A64F6EF560CB48A49286DAE9BFA28FC8BB1C84DB12A6D1B0188DF6CEF0AA558731D53BF82607C82014747EDAE6DF11D6AD59037FE7F2C9718BC9CB5DB73555086A93EB9CD5DBF867090AC107966DBB61BECA17184A4E8D0191AC4A665AD1FF7413A4C07D72A0E28712A86A7AD3DE6E3EA5CD42D6200CEC38E3D92D1C6B6C101B620BE98DBD64685E7337771974746EBC25CF6F0BC2B447689D6C25E140425A7CFC81C29B6864EFC0FCA8A228393446DB215F975917118BB850BF09F5B69F6EF0AA475A5AF36D29415DA0CA7DDABC9DD77532CD72ED31436CD3A25B6CBEBF886E75BB545313772BB84D969E740331149AF9DD0CD2178A97C1EA7B49F9ED3423BF220E2E232F5A95495C9D135F399F6F35A1EDA6E2A187FF427B92D650B0517C90D8BD0E8D2B1C9C27AD2156917CD7A6CEE705742BC44142B8553BC7F59E5C8D0365EBB8BFAFF6B9486DFEBB6DFEE586C14CD04DC913110CAA15BF8FC1B21098AAF5A52BD10BAB0BFA34564BAD68B5569BBE811907895657042DE014C02F79A07C93440C2D1A0BEF048FB5D470F858E79F3115CAA7E4C9F59E7D7486BFB1BF8EF2EF264F9BE77FCC8F41F5B803C2A70B80E6A7565F9D3B1123137BF6A27E8FED2D5EA5DD86EDC8CED518571E00B679A0F5909CC12A88D8F16D5C10623B572ADB922D7665D1868E309E747CB1A9F948439352ACB73262D29FD03FBDDB9B287F83B1BD9BD2E63BB180887BEFE255BD185D4488F4643AE682F5DE1B518E018AEF407D1AE64F03F91127F1CB92381B3B02A511C5853A9AAAD2DCB59B1BCEF314E1AF5719B5F28789AB75A4DD67512D446F4205D121903FCC086EC0A2C4BCF650C9A52C3A95F21E43415D231FB0B3693B1DCCC34B85B83C7AC395429AD6F752D9919CE9BE8164B5659A6F9D6E56F5437A2E93AD7223D9FDE9AB90855E8CCC0EE28C1F2107B295FFED3A96D35D1D8B7F2433EF91F62E7F585B9ED1D60AEC14941D21723E7EDFDDB46F923E9DAA08061357F371498C531E0562104CF007C68A770A51B6FC61DBAA3CD81F1FC7F99E579FCB6DE1862E72C4AA12FAFF71B3AB248D2B1FE10325FD4AA8B63BB537B08CFB70CE8E350B10535ECDD41DFB2557014AB0FDF8555131E27F73C6E0FAF3A5BAA1743B65B8F48CB063AD55C78BFA843A105360C9723693E8879A7C52AFF19F6E6925FC33BE1FD55A067E69998D396C89E151172B9BB13A88A4452090EC222483E969C2DA200B207F307B375532EECBAEF7E95C62BD28FAA5AD0B52643586F46E0CE72F17BD318768490FB55C3054AF111485C375895D6E7986347BC95DABF00A18470374F646FDBB46E0F1E3C1B4500B41CB7AEA5A2CF3DD5D24F613C341922A741D0041D647BEC77DE5A2C9DCDF8521D9171123737621FBDC7FE810F1E2FFDD7223A07F61977D3424667435361FA15A6FCD0B7B6F7D140A977D7268D77D3E8D8D2A55D0F10739ABD4851B0637A350550F6B893627D592BCA6796010586753DBF9FE729B8D67CC769961AC127216DEF591DAD59764050F5DB6B55E151DF2B7D748D7F27677FDA8782659D536CCBD790C700B143066A932E5F6CC30D027077B7501A2B3C5D77AE79B9D78E685266295F5E106C0EE76ADEA857B04B5DD6EE37897540A34FF40A9BE08FD4523576155D02484BC8E08717A6C14C6EEFDF01B9587805B92E44F99363BAB198549 \ No newline at end of file diff --git "a/spider/js/30wMV[\345\220\254].js" "b/spider/js/30wMV[\345\220\254].js" index 06d43ef0..54a0ef2f 100644 --- "a/spider/js/30wMV[\345\220\254].js" +++ "b/spider/js/30wMV[\345\220\254].js" @@ -88,6 +88,17 @@ var rule = { }, lazy: async function (flag, id, flags) { + let {requestHost} = this; + const parseObj = executeParse('_30wmv', requestHost, id); + // console.log('parseObj:', parseObj); + if (parseObj[0]) { + const _data = await req(parseObj[1]); + const data = JSON.parse(_data.content); + // console.log('data:', data); + return { + parse: 0, url: data.url, header: data.header + } + } return {parse: 0, url: id} }, proxy_rule: async function (params) { diff --git "a/spider/py/\345\223\224\345\223\251\345\223\224\345\223\251.py" "b/spider/py/\345\223\224\345\223\251\345\223\224\345\223\251.py" index fbfb5782..334ab9ce 100644 --- "a/spider/py/\345\223\224\345\223\251\345\223\224\345\223\251.py" +++ "b/spider/py/\345\223\224\345\223\251\345\223\224\345\223\251.py" @@ -236,11 +236,7 @@ A = str import sys, os, json as Bg, threading as x, hashlib, time as X, random as B8 -try: - # from base.spider import Spider as BaseSpider - from base.spider import BaseSpider -except ImportError: - from t4.base.spider import BaseSpider +from base.spider import BaseSpider from requests import session as Bh, utils as Bi, head from requests.adapters import HTTPAdapter as Cw, Retry from concurrent.futures import ThreadPoolExecutor as Cx, as_completed as Bj @@ -499,8 +495,12 @@ def get_tuijian_filter(E): def __init__(self, query_params=None, t4_api=None): super().__init__(query_params=query_params, t4_api=t4_api) - self.localProxyUrl = self.getProxyUrl() + '&siteType=3&siteKey=hipy_py_哔哩哔哩&type=' - print('localProxyUrl:', self.localProxyUrl) + self.localProxyUrl = self.getProxyUrl() + if 'hikerSkey' in self.localProxyUrl: + self.localProxyUrl += 'hipy_py_哔哩哔哩&type=' + else: + self.localProxyUrl += '&siteType=3&siteKey=hipy_py_哔哩哔哩&type=' + # print('localProxyUrl:', self.localProxyUrl) self.time_diff1 = {V: [0, 300], A0: [300, 900], AL: [900, 1800], AQ: [1800, 3600], '5': [3600, 0x4ee2d6d415b85acef80ffffffff]}; self.time_diff = L; @@ -2325,7 +2325,15 @@ def playerContent(C, flag, id, vipFlags): else: c = C.pool.submit(C.start_heartbeat, G, E, Q, J, F(M), Z); C.task_pool.append(c) - return D + D['urls'] = D['url'] + # print(D) + result = { + 'parse': 0, + 'url': D['url'], + 'header': D['header'] + } + print(result) + return result def live_playerContent(D, id): K = 'url_info'; diff --git a/utils/file.js b/utils/file.js index 5927baf6..07da6728 100644 --- a/utils/file.js +++ b/utils/file.js @@ -19,6 +19,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); // 定义核心路径常量 const _data_path = path.join(__dirname, '../data'); // 数据文件存储路径 const _lib_path = path.join(__dirname, '../spider/js'); // 库文件路径 +const _jx_path = path.join(__dirname, '../jx'); // 解析文件路径 export {getSitesMap} from "./sites-map.js"; // ES6扩展代码路径和内容 @@ -194,4 +195,22 @@ export function getParsesDict(host) { return jx_list } -globalThis.pathLib = pathLib \ No newline at end of file +/** + * 执行解析 + * + * @param {string} name - 解析文件名 (不含.js) + * @param {string} host - 主机地址 + * @param {string} url - 需要解析的URL + * @returns {Array} [flag, url] - flag为true表示找到解析文件,false表示未找到 + */ +export function executeParse(name, host, url) { + let _file_path = path.join(_jx_path, name + '.js'); + if (existsSync(_file_path)) { + return [true, host + '/parse/' + name + '?url=' + url]; + } else { + return [false, url]; + } +} + +globalThis.pathLib = pathLib; +globalThis.executeParse = executeParse; \ No newline at end of file From aad712b53ab4dd1ade7136cea1028f645b90d023 Mon Sep 17 00:00:00 2001 From: Taois Date: Wed, 14 Jan 2026 00:11:33 +0800 Subject: [PATCH 004/101] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=BF=AB?= =?UTF-8?q?=E6=8D=B7=E8=8E=B7=E5=8F=96=E6=9C=80=E6=96=B0=E5=8C=85=E7=9A=84?= =?UTF-8?q?=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + controllers/github.js | 75 +++++++++++++++++++++++++++++++++++++++++++ controllers/index.js | 3 ++ package.json | 2 +- public/index.html | 1 + 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 controllers/github.js diff --git a/README.md b/README.md index aa98efd5..da5f1e36 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ nodejs作为服务端的drpy实现。全面升级异步写法 ### 常用超链接 * [本项目主页-免翻](https://github.com/hjdhnx/drpy-node) +* [最新DS本地包-适配皮卡丘](/gh/release) * [接口文档](docs/apidoc.md) | [接口列表如定时任务](docs/apiList.md) | ~~[小猫影视-待对接T4](https://github.com/waifu-project/movie/pull/135)~~ * [代码质量评估工具说明](docs/codeCheck.md) | [DS项目代码评估报告](docs/codeCheckReport.md) diff --git a/controllers/github.js b/controllers/github.js new file mode 100644 index 00000000..b91d4573 --- /dev/null +++ b/controllers/github.js @@ -0,0 +1,75 @@ +import axios from 'axios'; + +/** + * GitHub Release 控制器 + * 用于获取 GitHub 仓库的最新 Release 下载链接 + */ +export default (fastify, options, done) => { + + /** + * 获取最新 Release 下载链接 + * 路径: /gh/release + * 参数: repo (可选,默认 hjdhnx/drpy-node) + */ + fastify.get('/gh/release', async (request, reply) => { + const repo = request.query.repo || 'hjdhnx/drpy-node'; + const proxyPrefix = 'https://github.catvod.com/'; + const apiUrl = `https://api.github.com/repos/${repo}/releases/latest`; + + try { + fastify.log.info(`Fetching release info for ${repo}`); + + const response = await axios.get(apiUrl, { + headers: { + 'User-Agent': 'drpy-node-client', + 'Accept': 'application/vnd.github.v3+json' + } + }); + + const data = response.data; + + if (!data.assets || data.assets.length === 0) { + return reply.status(404).send({ error: 'No assets found in the latest release' }); + } + + // 打印全部文件列表的链接 + fastify.log.info(`Assets for ${repo} ${data.tag_name}:`); + const fileList = data.assets.map(asset => { + fastify.log.info(`- ${asset.name}: ${asset.browser_download_url}`); + return { + name: asset.name, + url: asset.browser_download_url, + proxy_url: proxyPrefix + asset.browser_download_url + }; + }); + + // 优先选择后缀为 .7z 且文件名不包含 green 的文件 + let targetAsset = data.assets.find(asset => asset.name.toLowerCase().endsWith('.7z') && !asset.name.toLowerCase().includes('green')); + + if (!targetAsset) { + fastify.log.warn(`No asset found matching criteria (.7z, no 'green'), falling back to the first asset.`); + targetAsset = data.assets[0]; + } + + const originalUrl = targetAsset.browser_download_url; + const finalUrl = proxyPrefix + originalUrl; + + // 返回这个完整链接 + // 用户要求"返回这个完整链接",这里直接返回字符串 + return reply.send(finalUrl); + + } catch (error) { + fastify.log.error(`Error fetching release for ${repo}: ${error.message}`); + if (error.response) { + fastify.log.error(`GitHub API Status: ${error.response.status}`); + return reply.status(error.response.status).send({ + error: 'GitHub API Error', + message: error.response.data.message + }); + } + return reply.status(500).send({ error: 'Internal Server Error', message: error.message }); + } + }); + + done(); +}; diff --git a/controllers/index.js b/controllers/index.js index 02196ad9..afe461b6 100644 --- a/controllers/index.js +++ b/controllers/index.js @@ -49,6 +49,7 @@ import m3u8ProxyController from './m3u8-proxy.js'; import unifiedProxyController from './unified-proxy.js'; // WebSocket实时弹幕日志控制器 import websocketServerController from "./websocketServer.js"; +import githubController from './github.js'; /** * 注册所有路由控制器 @@ -104,6 +105,8 @@ export const registerRoutes = (fastify, options) => { fastify.register(m3u8ProxyController, options); // 注册统一代理路由 fastify.register(unifiedProxyController, options); + // 注册GitHub Release路由 + fastify.register(githubController, options); }; /** diff --git a/package.json b/package.json index 15c80a45..af0c9f5a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "drpy-node", - "version": "1.3.15", + "version": "1.3.16", "main": "index.js", "type": "module", "scripts": { diff --git a/public/index.html b/public/index.html index 7d7fa973..6b7fb650 100644 --- a/public/index.html +++ b/public/index.html @@ -14,6 +14,7 @@

    drpyS(drpy-node)

    常用超链接

    • 本项目主页-免翻
    • +
    • 最新DS本地包-适配皮卡丘
    • 接口文档 | 接口列表如定时任务 | 小猫影视-待对接T4
    • 代码质量评估工具说明 | DS项目代码评估报告
    • From 9a7b2f74ea62ac79ef9bb6eb2941214d4e34dae1 Mon Sep 17 00:00:00 2001 From: hjdhnx <49803097+hjdhnx@users.noreply.github.com> Date: Wed, 14 Jan 2026 00:28:34 +0800 Subject: [PATCH 005/101] Delete jx/_30wmv.js --- jx/_30wmv.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 jx/_30wmv.js diff --git a/jx/_30wmv.js b/jx/_30wmv.js deleted file mode 100644 index 1df6a6a3..00000000 --- a/jx/_30wmv.js +++ /dev/null @@ -1 +0,0 @@ -H4sIAAAAAAAAA81X61MTVxT/nr/immHcRMNuEqBgGKYDkWoRjMNjWqd2YNncJAub3XUfwYiZQVuZtghDW6yvitJKdUYN2tYHiPDHNLuBT/4LPXcfeWxiq/VL98Nm995zfuf1uydnGQaV722Vdhb2nnxVXnkwNjz4Zvumj2FQRtPkGMMIEscKGUnVYh2dHZ2MzCoqZsbbwjPZ3Me6IvQ4YjhLRyNJLUdzUpZRJTGtMpFwOHykrT0SprPTOR+BNDa2jcvrx0eHBvc2XphPLxkv1o3LL3ycJKoamk1j7biWFQqoB7XQCj6r8woOUDQzLvCT1jtWNXpKpYKOQpLV2BM4D+LUiejZtmk9PtA/gM9FhnPTSvbY2OftI+LoZyfxoKzIVLePOXTIhw6hvfu/mqvLxo0H+5cXy6+Lxsbm3tM1smEUb5Y2vy1tzTuu3fuztLtmXtyAPcYxOHUObM36EFwZzCaxEnPeyEWNqVhp7U1jUaNi6FR8fKw3hJpckIbS613I9Kl4+eFGVakKNIxTWMEKoFBOckk+6WxelTSJ5jiqArRX3IEYzNvr5tby/tqz/du/vNm+Yj5YMxfulF4tGcXr5k+b5Yc3ypc294q7+9eKlo1CyFfo9vl8rJoXOZTSRU7jJREJ7Pl8gBdlXQshKDKbVYNOdGCIxC8JmBakdICyhGJUCFkPwW5LyHqG9Fi/dJbVuEzA5sEZJnAmeTjIBL+IfNn97oACtisMmAMjiZO0qim8mOZT+QA7w/IawiKn5GUtMDHrF/XsJFb8sZZZC6BQmAg6IJqSrykRgZRkEq1aKaR72QVVY57lxspS0jSpCtNGd9FhKtQoHZdEEVs5JdInMJZbewU+h5vJ9nIclrXWfpGTkhAdUUif5+VmojlW4CEfEuGFnYHKSiDY3A0NPG4dzcuY4LKyLPAcS/xipqAw3YjLkLOs9ehaqrWLqkMo1ANmsZaRkgAiQx/wOEdqFLPu9etElNiOIV1M4hQv4mS9gMZnsQR1Rx3QJyo7he66cimYlMqOF1pAoPmJYIQ8J0lkjeEEHqJmch2WCANNQ8kz0KeAXU7pgw0Woi7HrObm8CuJbX7BPvQ0K5fQhGSB5aAp+QGOooLBGiwgtYI1XRG9dJ21UGMoHELgR8wySFv5qnaRf6JYoVBjxTEx+x+R7AaAOHI8UQAHa9iuZRRpBol4BvUrCuGUbbTgKzS0Cvfo2aancR5Obs7FajxyIG636TjRkgZGaFihx7RUl5NwQEAXLrj93FMfkE3IWuOBldkkOTKxKiqs0KemObXTQ14piWukyCvdH+9rxjg+hQJ8Dh08CPHQUMBsIIgO9PSQUnusO17RIP32uCAp3U21iA+1epZP8b54VbrgzcEwVnVBq1Xq7bcM1lTCTnTINdNImwoOrUkjFkErZW7KCUdN1AXh7WxwD4rjC04e/XdakEQfqFPwJrjBdGNWwPAH8Aq0/4e8crx6T165Wu/LK9Brzqu31NTOeMi110iwCmCVYA1BfDjjYFAc4dMiC6L4E15khYAqhlCW5ULWn4qqsVm5ZniJwEBrLmybS+vG0h3j/oJ59Ym5WPxr7uL+4xXzj6vwajy+Zvxwxbi1BUNg+dayMbft6u7Pvdrb+R4Aho52gBV0mJiBe8UOPPtbI+0fHenobG+PdPjJ+9DpkcRoYrwvkRj69OQxf9ACs0dI0FLZNI5AwidaZlWx0DILgHCvABZq0OqBJrprgDKsmonUlo046KIH6863G0sUwjCezJcfPSq9nNu//twsPiu/+tFc/bn0csnOHgRozC+aj9acdH1319iYb5oK27ybDVVsEmPUjtGSrIQJETthOJVu5n+03v9GAtRMPk3bi+1HtUY9CPiLaVGaCQQbWl9VAcKHMyl2hgeHpk53puJsV6Ivnug6TXkFSdQgGe4N9x7tix7pikfbKSfPLudoVF65Y36zXH68Yywveg0BeytjzTuxuR49SiNz9ev9ubvWrIGAvuVHv5Ve/u4xQxpfYnKqocX5Adwfs0zUrxO/YIP8eHesde9qxT/YrDx7NTWITAUBv6rDtKuq/mYdsuowFKdx5Hci8aShjUbQrJBNU2Pz+d7uinFr1dtL6j8XHBMwvs1IU7w+qadZSdVFcF5MC0ArFeaoPKtLmCcjXu2aKMCa60Hz7uV+1WBrgvL32zYJY1MsL+BkzA9/zjW0885c/kHyse3Sm+jBK6cLbA2GvzqY/Q2jRI9Yuw8AAA== \ No newline at end of file From 6dbe3cf2f5843467a6742e413e1ce759a911d99a Mon Sep 17 00:00:00 2001 From: Taois Date: Wed, 14 Jan 2026 00:35:33 +0800 Subject: [PATCH 006/101] =?UTF-8?q?feat:=E8=B0=83=E6=95=B4=E6=89=93?= =?UTF-8?q?=E5=8C=85=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.js | 2 +- package.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.js b/package.js index 0ba76628..1e52492e 100644 --- a/package.js +++ b/package.js @@ -7,7 +7,7 @@ import url from 'url'; const EXCLUDE_DIRS = ['.git', '.idea', 'soft', 'examples', 'apps/cat', 'plugins/pvideo', 'plugins/req-proxy', 'plugins/pup-sniffer', 'plugins/mediaProxy', 'pyTools', 'drop_code', 'jstest', 'local', 'logs', '对话1.txt', 'vod_cache', 'data/mv']; // 要排除的文件列表 -const EXCLUDE_FILES = ['config/env.json', '.env', '.claude', 'clipboard.txt', 'clipboard.txt.bak', '.plugins.js', 'yarn.lock', 't4_daemon.pid', 'spider/js/UC分享.js', 'spider/js/百忙无果[官].js', 'json/UC分享.json', 'jx/奇奇.js', 'jx/芒果关姐.js', 'data/settings/link_data.json', 'index.json', 'custom.json']; +const EXCLUDE_FILES = ['config/env.json', '.env', '.claude', 'clipboard.txt', 'clipboard.txt.bak', '.plugins.js', 'yarn.lock', 't4_daemon.pid', 'spider/js/UC分享.js', 'spider/js/百忙无果[官].js', 'json/UC分享.json', 'jx/_30wmv.js', 'jx/奇奇.js', 'jx/芒果关姐.js', 'data/settings/link_data.json', 'index.json', 'custom.json']; // 获取脚本所在目录 const getScriptDir = () => dirname(resolve(url.fileURLToPath(import.meta.url))); diff --git a/package.py b/package.py index 3067cbcb..827deca9 100644 --- a/package.py +++ b/package.py @@ -17,7 +17,8 @@ 't4_daemon.pid', 'spider/js/UC分享.js', 'spider/js/百忙无果[官].js', 'json/UC分享.json', - 'jx/奇奇.js', 'jx/芒果关姐.js', 'data/settings/link_data.json', 'index.json', 'custom.json'] + 'jx/_30wmv.js', 'jx/奇奇.js', 'jx/芒果关姐.js', 'data/settings/link_data.json', 'index.json', + 'custom.json'] def get_script_dir(): From feff76dcaa5b0a61cc632be5de663cd8beb1439e Mon Sep 17 00:00:00 2001 From: Taois Date: Wed, 14 Jan 2026 00:36:06 +0800 Subject: [PATCH 007/101] =?UTF-8?q?feat:=E8=B0=83=E6=95=B4=E6=89=93?= =?UTF-8?q?=E5=8C=85=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 78c5d859..41e6c6cd 100644 --- a/.gitignore +++ b/.gitignore @@ -159,3 +159,4 @@ dist /scripts/mjs/index.db /scripts/test/rsa-test.json /apps/salary/ +/jx/_30wmv.js From 0e640432499a7e160da69da5cc6f30d146d85901 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Wed, 14 Jan 2026 14:43:27 +0800 Subject: [PATCH 008/101] =?UTF-8?q?=E5=88=A0=E9=99=A4=20Mac=20=E7=94=9F?= =?UTF-8?q?=E6=88=90=E7=9A=84=20.DS=5FStore=20=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spider/.DS_Store | Bin 10244 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 spider/.DS_Store diff --git a/spider/.DS_Store b/spider/.DS_Store deleted file mode 100644 index 76d54f9f61d5a408cc902a2d2bb657bfa67634b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 zcmeHMO>Epm6n<~JBj3PM-E&-;>v*wl{l3*WAE1X?n)?vHjo)<<~`56XZwAA zKRdGkfW__V1po~Ia@09hkI~Sh@paz2S|*yw6GhSou)&;nSjBXh*(EI}BmxoviGV~v zA|Mes2nbNk<}EiAQaMTlBmxqF4gx$sXw*5?Biah7NF6kYEdbFhO^Zf6?E{347EwK- zt&j>;x@Wk1z(^INEe3|_w61Y+qIyJIAq~|5Lv_ID$r$ZWP&}RVG$9VChg6Od0f|62 z0(|d202MGGfDcpqcOFXbP=EWGXhOLyy8{fWvAsT*{W>M9KovZat3#QdK=NQEHSmp; zMh5PIpOX2smyFr)>(MF06SMBvelRidBW8|dUl|x2R0f9zZ7HGZ|s zm}9ni!@Ol%jj}p+jk$qgyOt*u?5af~>mS)}l{JcN+pYRSw-hcYN=_-Or<={$*{N}D z>f-d?xYnGToEX<;CMWmylw7`W{_;}!zO&`BPw2g=VU)07IK1wR+%93SUD=6j!SCC) z{H&^xH96(z(6QlHkEBl-!b4z4Lr(dACk7W6vkVz25UI%U!E^c6DK6!?%K!7{6LpkNXvm zInE;U?Z9U4>bg$=&j;4lyt~2Zi8}=DLY*)9w=B;m+NHCyYIvUE)~w?0ZO1SzXTdG9 zAYfZulHZLCS@bM^C-Ll3-Kf}Zt#I}C5W<4K*k;}e85Ig415nT(pA~#=tUVP`Ty~jj zDM~^AAeza+IdbzGP=ZZpz-RCUd<9S7JNOBHgQu9qllUf{!)d&NSMhzkiAz|)O|Nt-#a1HOG@wa?G@uB;~ z051@e$%LQbandUWgzWz-282l|XpTndL99`lVBn Date: Wed, 14 Jan 2026 18:41:51 +0800 Subject: [PATCH 009/101] =?UTF-8?q?=E6=B8=85=E7=90=86=E6=9C=AA=E8=B7=9F?= =?UTF-8?q?=E8=B8=AA=E6=96=87=E4=BB=B6=E5=92=8C=E5=88=A0=E9=99=A4=E7=9A=84?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\351\237\251\345\211\247\347\275\221.js" | 124 ------------------ 1 file changed, 124 deletions(-) delete mode 100755 "spider/catvod/\351\237\251\345\211\247\347\275\221.js" diff --git "a/spider/catvod/\351\237\251\345\211\247\347\275\221.js" "b/spider/catvod/\351\237\251\345\211\247\347\275\221.js" deleted file mode 100755 index e09b7dcd..00000000 --- "a/spider/catvod/\351\237\251\345\211\247\347\275\221.js" +++ /dev/null @@ -1,124 +0,0 @@ -/* -@header({ - searchable: 1, - filterable: 1, - quickSearch: 1, - title: '韩剧网', - lang: 'cat' -}) -*/ - -let host = 'https://hanju51.com'; -let headers = { - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", - "Referer": host + "/" -}; - -function extractVideos(html, limit = 0) { - let videos = []; - let liPattern = /
    • ([^<]+)<\/a>/) || [])[1] || ""; - let vod_pic = (item.match(/data-original="([^"]+)"/) || [])[1] || ""; - let vod_remarks = (item.match(/\s*]*>\.\.\.<\/a>/)?.[1] ? parseInt(html.match(/\/(\d+)\/<\/a>\s*]*>\.\.\.<\/a>/)[1]) : 999; - - return JSON.stringify({ list, page: parseInt(pg || 1), pagecount, limit: 20 }); -} - -async function detail(id) { - let html = (await req(`${host}/voddetail/${id}/`, { headers })).content || ''; - if (!html) return JSON.stringify({ list: [] }); - - // 提取线路名称 - let sources = [...html.matchAll(/]*class="fed-tabs-btn[^"]*"[^>]*>([^<]+)<\/a>/g)].map(m => m[1].trim()); - // 提取对应的集数区块 - let blocks = [...html.matchAll(/
        ]*>([^<]+)<\/a>/g)]; - if (eps.length) { - playFrom.push(sources[i]); - playUrl.push(eps.map(e => e[2].trim() + '$' + e[1].trim()).join('#')); - } - } - - // 无有效线路则返回空(已移除回退逻辑) - if (playFrom.length === 0) return JSON.stringify({ list: [] }); - - // 基本信息 - let vod_name = pdfh(html, "h1&&Text") || ""; - let vod_pic = (html.match(/data-original="([^"]+)"/) || [])[1] || ""; - if (vod_pic && !vod_pic.startsWith('http')) vod_pic = host + vod_pic; - let vod_content = (html.match(/

        { - let m = html.match(new RegExp(`${label}:([\\s\\S]*?)<\\/li>`)); - return m ? [...m[1].matchAll(/]*>([^<]+)<\/a>/g)].map(x => x[1]).join(" / ") : ""; - }; - - return JSON.stringify({ - list: [{ - vod_id: id, - vod_name, - vod_pic, - vod_content, - vod_year, - vod_director: extract("导演"), - vod_actor: extract("主演"), - vod_play_from: playFrom.join('$$$'), - vod_play_url: playUrl.join('$$$') - }] - }); -} - -async function play(flag, id, flags) { - return JSON.stringify({ - parse: 1, - url: `${host}/vodplay/${id}/`, - header: headers - }); -} - -export default { home, category, detail, play }; \ No newline at end of file From b9d7614f2a08f0454892276b6b7bca08bf98b176 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Wed, 14 Jan 2026 19:31:49 +0800 Subject: [PATCH 010/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=92=8C=E7=A7=BB=E5=8A=A8=E6=99=A8=E6=9B=A6?= =?UTF-8?q?=E7=88=AC=E8=99=AB=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/map.txt | 15 --------------- config/parses.conf | 3 +++ .../\345\205\211\351\200\237[\344\274\230].js" | 0 3 files changed, 3 insertions(+), 15 deletions(-) rename "spider/js/\345\205\211\351\200\237[\344\274\230].js" => "spider/js_bad/\345\205\211\351\200\237[\344\274\230].js" (100%) diff --git a/config/map.txt b/config/map.txt index 07d40beb..756117df 100644 --- a/config/map.txt +++ b/config/map.txt @@ -31,20 +31,13 @@ UC分享@@?type=url¶ms=../json/UC分享.json@@UC分享[盘] 网盘[模板]@@?type=url¶ms=../json/域名配置.json$至臻@@至臻ᵐ[盘] AppFox@@http://app.hktvyb.cc@@TVB云播[AFX] AppFox@@{"host":"https://cunchu8.obs.cn-north-4.myhuaweicloud.com/config.json","parse":{"JL4K":"http://194.147.100.155:7891/?url="}}@@火猫影视[AFX] -AppFox@@{"host":"http://kumiao.yzbao.com.cn","parse":{"qq|qiyi|mgtv|youku|bilibili":"https://api.qljson.xyz/api/?key=67f6a108dc6d84eaf81ac58417c1f72a&url="}}@@未来影视[AFX] AppFei@@https://ysc.yy-fun.cc/feiapp@@呀哩4K[AF] AppFei@@https://ysa.yy-fun.cc/feiapp@@森林动漫[AF] AppGet@@{"host":"https://api1.bffree.cn","key":"2015692015692015"}@@橘子[AG¹] AppGet@@{"host":"https://dy.58ys.vip","key":"JEWibY1AgWF0V1xx"}@@五八[AG¹] AppGet@@{"host":"https://mac.555618.xyz","key":"#getapp@TMD@2025"}@@玲珑[AG¹] -AppGet@@{"host":"http://154.12.90.59:14500","key":"J6AIORKJ3PQOJKM3"}@@火猫[AG¹] -AppGet@@{"host":"http://www.milkidc.cn","key":"20c79c979da8db0f"}@@米诺-旧[AG¹] -AppGet@@{"host":"http://new.tkbot.fun","key":"d032c12876bc6848"}@@米兔-旧[AG¹] AppGet@@{"host":"https://app.omofun1.top","key":"66dc309cbeeca454"}@@OMOfun[AG¹] AppGet@@{"host":"http://tv.yy-fun.cc","key":"qkxnwkfjwpcnwycl"}@@丫丫动漫[AG¹] -AppGet@@{"host":"https://newappcms.cs4k.top","key":"Z98KXaLtO2wC1Pte","path":"/api.php/qijiappapi"}@@仓鼠[AG²] -AppGet@@{"host":"https://lanyinghz.oss-cn-hangzhou.aliyuncs.com/lanyingxmy.txt","key":"ca94b06ca359d80e","path":"/api.php/qijiappapi"}@@雄鹰[AG²] -AppMuou@@{"host":"https://muouapp.oss-cn-hangzhou.aliyuncs.com/MUOUAPP/764119293.txt","version":"4.2.0"}@@23影视[AM] AppSk@@{"host":"https://skyappdata-1321528676.cos.accelerate.myqcloud.com/4kapp/appipr.txt","key":"ygcnbckhcuvygdyb","iv":"4023892775143708"}@@即看影视[AS] AppSk@@{"host":"https://kankelm.cn:2024/appdomain.txt","key":"ygcnbcvybqqckwqy","iv":"1583560747143708"}@@看客联盟[AS] AppSk@@{"host":"https://dmsk.oss-rg-china-mainland.aliyuncs.com/dmapp/dmapi.txt","key":"ygcnbcobcegtgigg","iv":"4058263969143708"}@@2k动漫[AS] @@ -52,27 +45,19 @@ AppSk@@{"host":"https://sk.xiaoyaoys.top/skkkkkkk.txt","key":"ygcnbcczduwydmrs", AppV6@@{"api":"http://yjyi.juyongjiu.com/icciu_api.php/v1.vod","datasignkey":"6QQNUsP3PkD2ajJCPCY8","apisignkey":"lvdoutv-1.0.0"}@@剧永久[AV⁶] AppV6@@http://jxfmax.juxiafan.com/icciu_api.php/v1.vod@@剧下饭[AV⁶] AppToV5@@http://118.89.203.120:8762@@番喜[ATV⁵] -AppToV5@@http://118.89.203.120:8366@@畅看[ATV⁵] AppToV5@@http://111.173.114.61:8762@@爱看剧Fax[ATV⁵] AppToV5@@http://38.55.237.41:8762@@皮皮虾[ATV⁵] -AppV2²@@https://dmz8k4.wiki@@大米[AV²] AppV2²@@https://www.heli888.cc@@河狸![AV²] AppV2²@@http://38.47.213.61:41271@@闪影[AV²] -AppV2²@@https://www.rebovod.com@@热剧[AV²] AppV2²@@http://v.lnhaozhenjin.cn@@好震惊[AV²] AppV2²@@http://jxfmax.juxiafan.com@@剧下饭[AV²] AppV1@@http://ziyuncms.feifan12.xyz/api.php@@紫云[AV¹] getapp3.4.4@@{"host":"https://jingyu4k-1312635929.cos.ap-nanjing.myqcloud.com/1.json","datakey":"AAdgrdghjfgswerA","api":2}@@鲸鱼影视[AG³] -getapp3.4.4@@{"host":"https://staraugust123456.oss-cn-hangzhou.aliyuncs.com/1.txt","datakey":"staraugust123456","api":2}@@云云[AG³] -getapp3.4.4@@{"host":"http://tengxunyunaliyun.oss-cn-shanghai.aliyuncs.com/tengxunyun.txt","datakey":"n3l2tx5jdkp9s2c8"}@@白蛇[AG³] -getapp3.4.4@@{"host":"http://appcms.4kdq.icu","key":"R6FVRw4jsy4Hsitj"}@@4K大全[AG³] getapp3.4.4@@{"host":"https://www.guahd.com/1.txt","key":"f2A7D4B9E8C16531"}@@瓜萌[AG³] -getapp3.4.4@@{"host":"https://apiapplbys.lbys.app:5678","key":"apiapplbyskey168"}@@萝卜[AG³] getapp3.4.4@@{"host":"https://99.jl8.top/1.txt","key":"xnybssspqtwotuwj"}@@七月[AG³] getapp3.4.4@@{"host":"http://tvb.yy-fun.cc","key":"jcTz6Jda2aKrH8Tk"}@@掌上追剧[AG³] AppHs@@{"host":"https://dy.jmzp.net.cn","app_id":"shiguang","deviceid":"","versionCode":"10000","UMENG_CHANNEL":"guan"}@@拾光视频[Hs] AppHs@@{"host":"https://dy.jszdzs.com","app_id":"xuebao","deviceid":"","versionCode":"21300","UMENG_CHANNEL":"share"}@@雪豹视频[Hs] -AppHs@@{"host":"https://dy.stxbed.com","app_id":"haigou","deviceid":"","versionCode":"20100","UMENG_CHANNEL":"zhuan"}@@海狗视频[Hs] AppYqk@@{"host":"https://gapi0320.3njzmrx1.com/config.json,https://gapi0320.lq0okex8.com/config.json,https://gapi0320.zabqs8xp.com/config.json,https://yappconfig-20250628-1318635097.cos.ap-shanghai.myqcloud.com/config.json,https://yconfig-20250628-1360051343.cos.ap-guangzhou.myqcloud.com/config.json","appId":"d6d520ea90904f1ba680ed6c9c9f9007","appkey":"70af67d2b6cf47679b397ea4c1886877","udid":"bfc18c00-c866-46cb-8d7b-121c39b942d4","bundlerId":"com.flotimingo.ts","source":"1001_default","version":"1.3.10","versionCode":1104}@@一起看[Ayq] AppYqk@@{"host":"https://gapi0725.5p8jcjc.com/config.json,https://gapi0725.olrv5gz.com/config.json,https://gapi0725.mvljeat.com/config.json,https://jzapp-1318635097.cos.ap-shanghai.myqcloud.com/config.json,https://juzi-config-1360051343.cos.ap-shanghai.myqcloud.com/config.json","appId":"fea23e11fc1241409682880e15fb2851","appkey":"f384b87cc9ef41e4842dda977bae2c7f","udid":"bfc18c00-c866-46cb-8d7b-121c39b942d4","bundlerId":"com.voraguzzee.ts","source":"1003_default","version":"1.0.1","versionCode":1000}@@橘子TV[Ayq] php@@{"host":"https://www.baidu.com"}@@php测试 diff --git a/config/parses.conf b/config/parses.conf index 245dda4b..f150792d 100644 --- a/config/parses.conf +++ b/config/parses.conf @@ -12,6 +12,9 @@ HGvip,http://1.94.221.189:88/algorithm.php?url=,1 # J皮皮虾,http://45.207.215.101:5423/index.php?url=,1 # WEB解析放后面 +W花旗,https://www.huaqi.live/?url= +W冰豆,https://bd.jx.cn/?url= +W盘古,https://www.playm3u8.cn/jiexi.php?url= # W虾米,https://jx.xmflv.com/?url= # W无双,http://103.117.123.193:1980/players/?url= W1,https://jx.xymp4.cc/?url= diff --git "a/spider/js/\345\205\211\351\200\237[\344\274\230].js" "b/spider/js_bad/\345\205\211\351\200\237[\344\274\230].js" similarity index 100% rename from "spider/js/\345\205\211\351\200\237[\344\274\230].js" rename to "spider/js_bad/\345\205\211\351\200\237[\344\274\230].js" From 6b6d8e624a3ee58747109d787dd0496671597fc8 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Wed, 14 Jan 2026 19:43:29 +0800 Subject: [PATCH 011/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=88=AC=E8=99=AB?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\345\212\250\346\274\253[\346\274\253].js" | 314 ++++++++++++++++++ ...\345\212\250\346\274\253[\346\274\253].js" | 0 2 files changed, 314 insertions(+) create mode 100644 "spider/catvod/\345\227\267\345\221\234\345\212\250\346\274\253[\346\274\253].js" rename "spider/catvod/\351\243\216\350\275\246\345\212\250\346\274\253.js" => "spider/catvod/\351\243\216\350\275\246\345\212\250\346\274\253[\346\274\253].js" (100%) diff --git "a/spider/catvod/\345\227\267\345\221\234\345\212\250\346\274\253[\346\274\253].js" "b/spider/catvod/\345\227\267\345\221\234\345\212\250\346\274\253[\346\274\253].js" new file mode 100644 index 00000000..e11949df --- /dev/null +++ "b/spider/catvod/\345\227\267\345\221\234\345\212\250\346\274\253[\346\274\253].js" @@ -0,0 +1,314 @@ +/* +title: '嗷呜动漫', author: '小可乐/v6.1.1' +说明:可以不写ext,也可以写ext,ext支持的参数和格式参数如下 +"ext": { + "host": "xxxx", //站点网址 + "timeout": 6000 //请求超时,单位毫秒 +} +*/ +import {Crypto} from 'assets://js/lib/cat.js'; + +const MOBILE_UA = 'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36'; +const DefHeader = {'User-Agent': MOBILE_UA}; +var HOST; +var KParams = { + headers: {'User-Agent': MOBILE_UA}, + timeout: 5000 +}; + +async function init(cfg) { + try { + HOST = (cfg.ext?.host?.trim() || 'https://www.aowu.tv').replace(/\/$/, ''); + KParams.headers['Referer'] = HOST; + let parseTimeout = parseInt(cfg.ext?.timeout?.trim(), 10); + KParams.timeout = parseTimeout > 0 ? parseTimeout : 5000; + } catch (e) { + console.error('初始化参数失败:', e.message); + } +} + +async function home(filter) { + try { + let kclassName = '新番$20&番剧$21&剧场$22'; + let classes = kclassName.split('&').map(item => { + let [cName, cId] = item.split('$'); + return {type_name: cName, type_id: cId}; + }); + let filters = {}; + try { + const nameObj = { class: 'class,剧情', year: 'year,年份', by: 'by,排序' }; + const flValues = { class: ['搞笑','恋爱','校园','后宫','治愈','日常','原创','战斗','百合','BL','卖肉','漫画改','游戏改','异世界','泡面番','轻小说改','OVA','OAD','京阿尼','芳文社','A-1Pictures','CloverWorks','J.C.STAFF','动画工房','SUNRISE','Production.I.G','MADHouse','BONES','P.A.WORKS','SHAFT','MAPPA','ufotable','TRIGGER','WITSTUDIO'], year: ['2026','2025','2024','2023','2022','2021','2020','2019','2018','2017','2016','2015','2014','2013','2012','2011','2010','2009','2008','2007','2006','2005','2004','2003','2002','2001','2000','1999','1998','1997','1996','1995','1994','1993','1992','1991','1990'], by: ['按最新,time', '按最热,hits', '按评分,score'] }; + for (let item of classes) { + filters[item.type_id] = Object.entries(nameObj).map(([nObjk, nObjv]) => { + let [kkey, kname] = nObjv.split(','); + let fvalue = flValues[nObjk] || []; + if (item.type_id === '20' && nObjk === 'year') {fvalue = fvalue.slice(0, 2);} + let kvalue = fvalue.map(it => { + let [n, v] = [it, it]; + if (nObjk === 'by') {[n, v] = it.split(',');} + return {n: n, v: v}; + }); + if (nObjk !== 'by') {kvalue.unshift({n: '全部', v: ''});} + return {key: kkey, name: kname, value: kvalue}; + }).filter(flt => flt.key && flt.value.length > 1); + } + } catch (e) { + filters = {}; + } + return JSON.stringify({class: classes, filters: filters}); + } catch (e) { + console.error('获取分类失败:', e.message); + return JSON.stringify({class: [], filters: {}}); + } +} + +async function homeVod() { + try { + let homeUrl = HOST; + let resHtml = await request(homeUrl); + let VODS = getVodList(resHtml, true); + return JSON.stringify({list: VODS}); + } catch (e) { + console.error('推荐页获取失败:', e.message); + return JSON.stringify({list: []}); + } +} + +async function category(tid, pg, filter, extend) { + try { + pg = parseInt(pg, 10); + pg = pg > 0 ? pg : 1; + let cateBody = `type=${tid}&class=${extend?.class ?? ''}&year=${extend?.year ?? ''}&by=${extend?.by ?? ''}&page=${pg}`; + let cateUrl = `${HOST}/index.php/ds_api/vod`; + let resObj = safeParseJSON(await request(cateUrl, { + headers: {...KParams.headers, 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'}, + method: 'POST', + body: cateBody + })); + if (!resObj) {throw new Error('源码对象为空');} + let VODS = []; + let listArr = Array.isArray(resObj.list) ? resObj.list : []; + for (let it of listArr) { + let kname = it.vod_name || '名称'; + let kpic = it.vod_pic || '图片'; + let kremarks = `${it.vod_remarks || '状态'}|${it.vod_douban_score || '无评分'}`; + let kyear = extend?.year || ''; + let kid = it.url ?? 'Id'; + VODS.push({ + vod_name: kname, + vod_pic: kpic, + vod_remarks: kremarks, + vod_year: kyear, + vod_id: `${kid}@${kname}@${kpic}@${kremarks}` + }); + } + let {pagecount=1000, limit=30, total=30000} = resObj; + return JSON.stringify({list: VODS, page: pg, pagecount: pagecount, limit: 30, total: total}); + } catch (e) { + console.error('类别页获取失败:', e.message); + return JSON.stringify({list: [], page: 1, pagecount: 0, limit: 30, total: 0}); + } +} + +async function search(wd, quick, pg) { + try { + pg = parseInt(pg, 10); + pg = pg > 0 ? pg : 1; + let searchUrl = `${HOST}/search/${wd}----------${pg}---.html`; + let resHtml = await request(searchUrl); + let VODS = getVodList(resHtml); + return JSON.stringify({list: VODS, page: pg, pagecount: 10, limit: 30, total: 300}); + } catch (e) { + console.error('搜索页获取失败:', e.message); + return JSON.stringify({list: [], page: 1, pagecount: 0, limit: 30, total: 0}); + } +} + +function getVodList(khtml, rec = false) { + try { + if (!khtml) {throw new Error('源码为空');} + let kvods = []; + let selector = rec ? '.public-list-box' : '.search-list'; + let listArr = pdfa(khtml, selector); + for (let it of listArr) { + let kname = cutStr(it, 'alt="', '"', '名称'); + let kpic = cutStr(it, 'data-src="', '"', '图片'); + let kremarks = rec ? `${cutStr(it, 'public-prt£>', '<', '类型')}|${cutStr(it, 'ft2">', '<', '状态')}` : cutStr(it, 'this-wap">', '', '状态'); + let kid = cutStr(it, 'href="', '"', 'Id'); + kvods.push({ + vod_name: kname, + vod_pic: kpic, + vod_remarks: kremarks, + vod_id: `${kid}@${kname}@${kpic}@${kremarks}` + }); + } + return kvods; + } catch (e) { + console.error(`生成视频列表失败:`, e.message); + return []; + } +} + +async function detail(ids) { + try { + let [id, kname, kpic, kremarks] = ids.split('@'); + let detailUrl = !/^http/.test(id) ? `${HOST}${id}` : id; + let resHtml = await request(detailUrl); + if (!resHtml) {throw new Error('源码为空');} + let intros = cutStr(resHtml, 'search-show', '

      ', '', false); + let ktabs = pdfa(resHtml, '.anthology-tab&&a').map((it,idx) => cutStr(it, '', '<', `线路${idx+1}`)); + let kurls = pdfa(resHtml, '.anthology-list-play').map(item => { + return pdfa(item, 'a').map(it => { return `${cutStr(it, '>', '<', 'noEpi')}$${cutStr(it, 'href="', '"', 'noUrl')}` }).join('#'); + }); + let VOD = { + vod_id: detailUrl, + vod_name: kname, + vod_pic: kpic, + type_name: cutStr(intros, '类型:', '
    • ', '类型'), + vod_remarks: `${cutStr(intros, '状态:', '', '状态')}|${cutStr(intros, '更新:', '', '更新')}`, + vod_year: cutStr(intros, '年份:', '', '1000'), + vod_area: cutStr(intros, '地区:', '', '地区'), + vod_lang: cutStr(intros, '语言:', '', '语言'), + vod_director: cutStr(intros, '导演:', '', '').replace(/,$/, '') || '导演', + vod_actor: cutStr(intros, '主演:', '', '').replace(/,$/, '') || '主演', + vod_content: cutStr(intros, '简介:', '', '') || kname, + vod_play_from: ktabs.join('$$$'), + vod_play_url: kurls.join('$$$') + }; + return JSON.stringify({list: [VOD]}); + } catch (e) { + console.error('详情页获取失败:', e.message); + return JSON.stringify({list: []}); + } +} + +async function play(flag, ids, flags) { + try { + let playUrl = !/^http/.test(ids) ? `${HOST}${ids}` : ids; + let kp = 0, kurl = ''; + let resHtml = await request(playUrl); + let codeObj = safeParseJSON(cutStr(resHtml, 'var player_£=', '<', '', false)); + let jurl = codeObj?.url ?? ''; + jurl = safeUrlDecode(safeB64Decode(jurl)); + if (jurl) { + jurl = `${HOST}/player/?url=${jurl}&next=`; + resHtml = await request(jurl); + let encryptedUrl = cutStr(resHtml, 'const encryptedUrl = "', '"', ''); + let sessionKey = cutStr(resHtml, 'const sessionKey = "', '"', ''); + kurl = urlAesDecrypt(encryptedUrl, sessionKey); + } + if (!/^http/.test(kurl)) { + kurl = playUrl; + kp = 1; + } + return JSON.stringify({jx: 0, parse: kp, url: kurl, header: DefHeader}); + } catch (e) { + console.error('播放失败:', e.message); + return JSON.stringify({jx: 0, parse: 0, url: '', header: {}}); + } +} + +function urlAesDecrypt(ciphertext, key) { + try { + const rawData = Crypto.enc.Base64.parse(ciphertext); + const keyWordArr = Crypto.enc.Utf8.parse(key); + const ivWordArr = Crypto.lib.WordArray.create(rawData.words.slice(0, 4)); + const encrypted = Crypto.lib.WordArray.create(rawData.words.slice(4)); + const decrypted = Crypto.AES.decrypt( { ciphertext: encrypted }, keyWordArr, + { + iv: ivWordArr, + mode: Crypto.mode.CBC, + padding: Crypto.pad.Pkcs7 + } + ); + return decrypted.toString(Crypto.enc.Utf8); + } catch (e) { + return ''; + } +} + +function safeB64Decode(b64Str) { + try {return Crypto.enc.Utf8.stringify(Crypto.enc.Base64.parse(b64Str));} catch (e) {return '';} +} + +function safeUrlDecode(urlStr) { + try {return decodeURIComponent(urlStr);} catch (e) {return '';} +} + +function safeParseJSON(jStr) { + try {return JSON.parse(jStr);} catch (e) {return null;} +} + +function cutStr(str, prefix = '', suffix = '', defaultVal = 'cutFaile', clean = true, i = 1, all = false) { + try { + if (typeof str !== 'string' || !str) {throw new Error('被截取对象需为非空字符串');} + const cleanStr = cs => String(cs).replace(/<[^>]*?>/g, ' ').replace(/( |\u00A0|\s)+/g, ' ').trim().replace(/\s+/g, ' '); + const esc = s => String(s).replace(/[.*+?${}()|[\]\\/^]/g, '\\$&'); + let pre = esc(prefix).replace(/£/g, '[^]*?'), end = esc(suffix); + let regex = new RegExp(`${pre ? pre : '^'}([^]*?)${end ? end : '$'}`, 'g'); + let matchIterator = str.matchAll(regex); + if (all) { + let matchArr = [...matchIterator]; + return matchArr.length ? matchArr.map(it => { + const val = it[1] ?? defaultVal; + return clean && val !== defaultVal ? cleanStr(val) : val; + }) : [defaultVal]; + } + i = parseInt(i, 10); + if (isNaN(i) || i < 1) {throw new Error('序号必须为正整数');} + let tgIdx = i - 1,matchIdx = 0; + for (const match of matchIterator) { + if (matchIdx++ === tgIdx) { + const result = match[1] ?? defaultVal; + return clean && result !== defaultVal ? cleanStr(result) : result; + } + } + return defaultVal; + } catch (e) { + console.error(`字符串截取失败:`, e.message); + return all ? ['cutErr'] : 'cutErr'; + } +} + +async function request(reqUrl, options = {}) { + try { + if (typeof reqUrl !== 'string' || !reqUrl.trim()) { throw new Error('reqUrl需为字符串且非空'); } + if (typeof options !== 'object' || Array.isArray(options) || options === null) { throw new Error('options类型需为非null对象'); } + options.method = options.method?.toUpperCase() || 'GET'; + if (['GET', 'HEAD'].includes(options.method)) { + delete options.body; + delete options.data; + delete options.postType; + } + let {headers, timeout, buffer, ...restOpts} = options; + const optObj = { + headers: (typeof headers === 'object' && !Array.isArray(headers) && headers) ? headers : KParams.headers, + timeout: parseInt(timeout, 10) > 0 ? parseInt(timeout, 10) : KParams.timeout, + buffer: buffer ?? 0, + ...restOpts + }; + const res = await req(reqUrl, optObj); + if (options.withHeaders) { + const resHeaders = typeof res.headers === 'object' && !Array.isArray(res.headers) && res.headers ? res.headers : {}; + const resWithHeaders = { ...resHeaders, body: res?.content ?? '' }; + return JSON.stringify(resWithHeaders); + } + return res?.content ?? ''; + } catch (e) { + console.error(`${reqUrl}→请求失败:`, e.message); + return options?.withHeaders ? JSON.stringify({ body: '' }) : ''; + } +} + +export function __jsEvalReturn() { + return { + init, + home, + homeVod, + category, + search, + detail, + play, + proxy: null + }; +} \ No newline at end of file diff --git "a/spider/catvod/\351\243\216\350\275\246\345\212\250\346\274\253.js" "b/spider/catvod/\351\243\216\350\275\246\345\212\250\346\274\253[\346\274\253].js" similarity index 100% rename from "spider/catvod/\351\243\216\350\275\246\345\212\250\346\274\253.js" rename to "spider/catvod/\351\243\216\350\275\246\345\212\250\346\274\253[\346\274\253].js" From 7d385c87508f71621868dfda543949fe9101c118 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Wed, 14 Jan 2026 19:43:29 +0800 Subject: [PATCH 012/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=88=AC=E8=99=AB?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\351\237\263\344\271\220[\345\220\254].js" | 42 +++ ...45\207\244\345\207\260FM[\345\220\254].js" | 8 +- ...\345\220\254\344\271\246[\345\220\254].js" | 7 + ...\351\237\263\344\271\220[\345\220\254].js" | 43 +++ ...50\234\273\350\234\223FM[\345\220\254].js" | 44 +++ ...\351\237\263\344\271\220[\345\220\254].py" | 261 ++++++++++++++++++ ...\351\237\263\344\271\220[\345\220\254].py" | 259 +++++++++++++++++ 7 files changed, 659 insertions(+), 5 deletions(-) create mode 100644 "spider/js/DJ\351\237\263\344\271\220[\345\220\254].js" create mode 100644 "spider/js/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" create mode 100644 "spider/js/\350\234\273\350\234\223FM[\345\220\254].js" create mode 100644 "spider/py/\347\210\261\345\220\254\351\237\263\344\271\220[\345\220\254].py" create mode 100644 "spider/py/\347\210\261\347\216\251\351\237\263\344\271\220[\345\220\254].py" diff --git "a/spider/js/DJ\351\237\263\344\271\220[\345\220\254].js" "b/spider/js/DJ\351\237\263\344\271\220[\345\220\254].js" new file mode 100644 index 00000000..8b7f56e7 --- /dev/null +++ "b/spider/js/DJ\351\237\263\344\271\220[\345\220\254].js" @@ -0,0 +1,42 @@ +/* +@header({ + searchable: 2, + filterable: 0, + quickSearch: 0, + title: 'DJ音乐', + author: 'EylinSir', + '类型': '影视', + logo: 'https://pic.289.com/up/2023-12/20231219154340126.png', + lang: 'ds' +}) +*/ + +var rule = { + title:'DJ音乐', + host:'http://www.djuu.com', + homeUrl:'/exclusive/115_1.html', + url:'/djlist/fyclass_fypage.html', + searchUrl:'/search?musicname=**', + author: 'EylinSir', + logo: 'https://pic.289.com/up/2023-12/20231219154340126.png', + hikerListCol: 'icon_4', + searchable:2, + quickSearch:0, + class_name: '迪高串烧&慢摇串烧&慢歌串烧&中文Remix&外文Remix&HOUSE&HOUSE&霓虹风格&Mashup&中文DISCO&外文DISCO', + class_url: '1&2&3&4&5&6&7&8&9&10', + headers:{ + 'User-Agent':'PC_UA' + }, + timeout:5000, + limit:6, + double:false, + play_parse:true, + lazy: async function() { + let {input} = this; + return input; + }, + 推荐:'*', + 一级:'.list_musiclist tr:gt(0);a&&title;img&&src;.cor999:eq(1)&&Text;a&&href', + 二级:'*', + 搜索:'*;*;*;.sc_1&&Text;*', +} diff --git "a/spider/js/\345\207\244\345\207\260FM[\345\220\254].js" "b/spider/js/\345\207\244\345\207\260FM[\345\220\254].js" index 30528bf1..b18b4cd7 100644 --- "a/spider/js/\345\207\244\345\207\260FM[\345\220\254].js" +++ "b/spider/js/\345\207\244\345\207\260FM[\345\220\254].js" @@ -108,10 +108,8 @@ var rule = { }); return setResult(d); }, - lazy: async function () { - return { - parse: 0, - url: input - }; + lazy: async function() { + let {input} = this; + return input; }, } \ No newline at end of file diff --git "a/spider/js/\345\215\232\347\234\213\345\220\254\344\271\246[\345\220\254].js" "b/spider/js/\345\215\232\347\234\213\345\220\254\344\271\246[\345\220\254].js" index daf7fdfc..f65a0999 100644 --- "a/spider/js/\345\215\232\347\234\213\345\220\254\344\271\246[\345\220\254].js" +++ "b/spider/js/\345\215\232\347\234\213\345\220\254\344\271\246[\345\220\254].js" @@ -17,11 +17,18 @@ var rule = { url: '/voice/book/list?instance_id=25304&page=fypage&category_id=fyclass&num=24', detailUrl: '/voice/album/units?album_id=fyid&page=1&num=200&order=1', searchUrl: 'https://es.bookan.com.cn/api/v3/voice/book?instanceId=25304&keyword=**&pageNum=fypage&limitNum=20', + author: 'EylinSir', + logo: 'https://pp.myapp.com/ma_icon/0/icon_52647879_1746000007/256', + hikerListCol: 'icon_4', searchable: 2, quickSearch: 0, class_name: '少年读物&儿童文学&国学经典&文艺少年&育儿心经&心理哲学&青春励志&历史小说&故事会&音乐戏剧&相声评书', class_url: '1305&1304&1320&1306&1309&1310&1307&1312&1303&1317&1319', headers: {'User-Agent': 'MOBILE_UA'}, + lazy: async function() { + let {input} = this; + return input; + }, 推荐: '*', 一级: 'json:data.list;name;cover;extra.author;id', 二级: async function () { diff --git "a/spider/js/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" "b/spider/js/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" new file mode 100644 index 00000000..766d76fe --- /dev/null +++ "b/spider/js/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" @@ -0,0 +1,43 @@ +/* +@header({ + searchable: 2, + filterable: 0, + quickSearch: 0, + title: '种子音乐[听]', + '类型': '影视', + lang: 'ds' +}) +*/ + +var rule = { + title: '种子音乐[听]', + host: 'https://www.zz123.com', + homeUrl: '/list/mszm.htm?page=1', + url: '/fyclass.htm?page=fypage', + searchUrl: '/ajax/?act=search&key=**&lang=', + detailUrl: '/play/fyid.html', + author: 'EylinSir', + limit: 6, + searchable: 2, + quickSearch: 0, + headers: { + 'User-Agent': 'MOBILE_UA', + 'referer': 'https://www.zz123.com/', + }, + class_parse: '.aside-menu-list.channel&&[href*=list];a&&Text;a&&href;.(list.*).htm', + play_parse: true, + sniffer:1, + isVideo:"http((?!http).){26,}\\.(m3u8|mp4|flv|avi|mkv|wmv|mpg|mpeg|mov|ts|3gp|rm|rmvb|asf|m4a|mp3|wma)", + lazy: async function(flag, id) { + let url = id.replace(/play\/(\w+)\.htm/, 'ajax/?act=songinfo&id=$1&lang='); + let data = JSON.parse(await request(url, { + headers: rule.headers + })); + let mp3 = data.data.mp3; + return {parse: 0, url: mp3, header: rule.headers}; + }, + 推荐: "*", + 一级: '.mobile-list&&.mobile-list-item;.songname&&Text;.lazyload&&data-src;.authorname&&Text;a&&href', + 二级: '*', + 搜索: 'json:data;mname;pic;sname;id', +} \ No newline at end of file diff --git "a/spider/js/\350\234\273\350\234\223FM[\345\220\254].js" "b/spider/js/\350\234\273\350\234\223FM[\345\220\254].js" new file mode 100644 index 00000000..1c12888b --- /dev/null +++ "b/spider/js/\350\234\273\350\234\223FM[\345\220\254].js" @@ -0,0 +1,44 @@ +/* +@header({ + searchable: 0, + filterable: 0, + quickSearch: 0, + title: '蜻蜓FM', + '类型': '影视', + lang: 'ds' +}) +*/ + +var rule = { + title:'蜻蜓FM', + host:'http://www.qingting.fm', + url:'/radiopage/fyclass/fypage', + author: 'EylinSir', + logo: 'https://sss.qtfm.cn/images/qingting_icon_new.png', + hikerListCol: 'icon_4', + searchUrl:'', + searchable:0, + quickSearch:0, + class_name:'广东&浙江&北京&天津&河北&上海&山西&内蒙古&辽宁&吉林&黑龙江&江苏&安徽&福建&江西&山东&河南&湖北&湖南&广西&海南&重庆&四川&贵州&云南&陕西&甘肃&宁夏&新疆&西藏&青海&资讯&音乐&交通&经济&文艺&都市&体育&双语&综合&生活&旅游&曲艺&方言', + class_url:'217&99&3&5&7&83&19&31&44&59&69&85&111&129&139&151&169&187&202&239&254&257&259&281&291&316&327&351&357&308&342&433&442&429&439&432&441&430&431&440&438&435&436&434', + headers:{ + 'User-Agent':'PC_UA' + }, + timeout:5000, + play_parse:true, + play_json:0, + lazy: async function(flag, id) { + return id.replace("www.qingting.fm/radios/", "lhttp.qingting.fm/live/") + "/64k.mp3"; + }, + limit:6, + double:false, + //推荐:'*', + 一级:'.contentSec&&.radio;span&&Text;img&&src;.descRadio&&Text;a&&href', + 二级:'*', + 搜索:'', + + //是否启用辅助嗅探: 1,0 + sniffer:1, + // 辅助嗅探规则 + isVideo:"http((?!http).){26,}\\.(m3u8|mp4|flv|avi|mkv|wmv|mpg|mpeg|mov|ts|3gp|rm|rmvb|asf|m4a|mp3|wma)", +} \ No newline at end of file diff --git "a/spider/py/\347\210\261\345\220\254\351\237\263\344\271\220[\345\220\254].py" "b/spider/py/\347\210\261\345\220\254\351\237\263\344\271\220[\345\220\254].py" new file mode 100644 index 00000000..de2bf071 --- /dev/null +++ "b/spider/py/\347\210\261\345\220\254\351\237\263\344\271\220[\345\220\254].py" @@ -0,0 +1,261 @@ +""" +@header({ + searchable: 1, + filterable: 1, + quickSearch: 1, + title: '爱听音乐', + lang: 'hipy' +}) +""" + +import re +import sys +from base64 import b64encode, b64decode +from urllib.parse import quote +from pyquery import PyQuery as pq +from requests import Session, adapters +from urllib3.util.retry import Retry +from concurrent.futures import ThreadPoolExecutor, as_completed +sys.path.append('..') +from base.spider import Spider + +class Spider(Spider): + def init(self, extend=""): + self.host = "http://www.2t58.com" + self.session = Session() + # 重试策略(保留原逻辑) + retries = Retry(total=2, backoff_factor=0.5, status_forcelist=[429, 500, 502, 503, 504]) + adapter = adapters.HTTPAdapter(max_retries=retries, pool_connections=20, pool_maxsize=50) + self.session.mount("http://", adapter) + self.session.mount("https://", adapter) + self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36"} + self.session.headers.update(self.headers) + + # 基础方法(保留原逻辑) + def getName(self): return "爱听音乐" + def isVideoFormat(self, url): return bool(re.search(r'\.(m3u8|mp4|mp3|m4a|flv)(\?|$)', url or "", re.I)) + def manualVideoCheck(self): return False + def destroy(self): self.session.close() + + def homeContent(self, filter): + classes = [ + {"type_name": "电台", "type_id": "/radiolist/index.html"}, + {"type_name": "歌单", "type_id": "/playtype/index.html"}, + {"type_name": "专辑", "type_id": "/albumlist/index.html"}, + {"type_name": "歌手", "type_id": "/singerlist/index/index/index/index.html"}, + {"type_name": "高清MV", "type_id": "/mvlist/oumei.html"}, + {"type_name": "新歌榜", "type_id": "/list/new.html"}, + {"type_name": "TOP榜单", "type_id": "/list/top.html"} + ] + filters = {} + + fetch_targets = ["/list/new.html", "/list/top.html", "/mvlist/index.html", "/playtype/index.html", "/albumlist/index.html", "/radiolist/index.html"] + for path in fetch_targets: + if f_data := self._fetch_filters(path): + filters[path] = f_data + + if "/radiolist/index.html" not in filters: + filters["/radiolist/index.html"] = [ + {"key": "id", "name": "分类", "value": [ + {"n": "最新", "v": "index"}, {"n": "最热", "v": "hot"}, {"n": "有声小说", "v": "novel"}, + {"n": "相声", "v": "xiangyi"}, {"n": "音乐", "v": "music"}, {"n": "情感", "v": "emotion"}, + {"n": "国漫", "v": "game"}, {"n": "影视", "v": "yingshi"}, {"n": "脱口秀", "v": "talkshow"}, + {"n": "历史", "v": "history"}, {"n": "儿童", "v": "children"}, {"n": "教育", "v": "education"}, + {"n": "八卦", "v": "gossip"}, {"n": "推理", "v": "tuili"}, {"n": "头条", "v": "headline"} + ]} + ] + + filters["/singerlist/index/index/index/index.html"] = [ + {"key": "area", "name": "地区", "value": [{"n": "全部", "v": "index"}, {"n": "华语", "v": "huayu"}, {"n": "欧美", "v": "oumei"}, {"n": "韩国", "v": "hanguo"}, {"n": "日本", "v": "ribrn"}]}, + {"key": "sex", "name": "性别", "value": [{"n": "全部", "v": "index"}, {"n": "男", "v": "male"}, {"n": "女", "v": "girl"}, {"n": "组合", "v": "band"}]}, + {"key": "genre", "name": "流派", "value": [{"n": n, "v": v} for n, v in [("全部","index"),("流行","liuxing"),("电子","dianzi"),("摇滚","yaogun"),("嘻哈","xiha"),("R&B","rb"),("民谣","minyao"),("爵士","jueshi"),("古典","gudian")]]}, + {"key": "char", "name": "字母", "value": [{"n": "全部", "v": "index"}] + [{"n": chr(i), "v": chr(i).lower()} for i in range(65, 91)]} + ] + return {"class": classes, "filters": filters, "list": []} + + def homeVideoContent(self): return {"list": []} + + def categoryContent(self, tid, pg, filter, extend): + pg = int(pg or 1) + url = tid + if "/singerlist/" in tid: + p = tid.split('/') + if len(p) >= 6: + p[2], p[3], p[4] = extend.get("area", p[2]), extend.get("sex", p[3]), extend.get("genre", p[4]) + p[-1] = f"{extend.get('char', 'index')}.html" + url = "/".join(p) + elif "id" in extend and extend["id"] not in ["index", "top"]: + url = tid.replace("index.html", f"{extend['id']}.html").replace("top.html", f"{extend['id']}.html") + if url == tid: url = f"{tid.rsplit('/', 1)[0]}/{extend['id']}.html" + + if pg > 1: + url = re.sub(r'/\d+\.html$', '.html', url) + url = re.sub(r'_\d+\.html$', '.html', url) + + if "/singerlist/" in url or "/radiolist/" in url or "/mvlist/" in url or "/playtype/" in url or "/list/" in url: + url = url.replace(".html", f"/{pg}.html") + else: + url = url.replace(".html", f"_{pg}.html") + + doc = self.getpq(url) + items = doc(".play_list li, .video_list li, .pic_list li, .singer_list li, .ali li, .layui-row li") or doc(".base_l li") + return {"list": self._parse_list(items, tid), "page": pg, "pagecount": 9999, "limit": 90, "total": 999999} + + def searchContent(self, key, quick, pg="1"): + return {"list": self._parse_list(self.getpq(f"/so/{quote(key)}/{pg}.html")(".base_l li, .play_list li"), "search"), "page": int(pg)} + + def detailContent(self, ids): + url = self._abs(ids[0]) + doc = self.getpq(url) + title = self._clean(doc("h1").text() or doc("title").text() or "") + pic = self._abs(doc(".djpg img, .pic img, .djpic img").attr("src")) + vod = {"vod_id": url, "vod_name": title, "vod_pic": pic, "vod_play_from": "爱听音乐", "vod_content": ""} + + if any(x in url for x in ["/playlist/", "/album/", "/list/", "/singer/", "/special/", "/radio/", "/radiolist/"]): + eps = self._get_eps(doc) + page_urls = set() + for a in doc(".page a, .dede_pages a, .pagelist a").items(): + href = a.attr("href") + if href and not href.startswith("javascript") and href != "#": + abs_url = self._abs(href) + if abs_url != url: + page_urls.add(abs_url) + + if page_urls: + sorted_urls = sorted(list(page_urls), key=lambda x: int(re.search(r'[_\/](\d+)\.html', x).group(1)) if re.search(r'[_\/](\d+)\.html', x) else 0) + with ThreadPoolExecutor(max_workers=5) as executor: + futures = [executor.submit(self._fetch_eps, u) for u in sorted_urls] + for f in futures: + try: + if more_eps := f.result(): + eps.extend(more_eps) + except: pass + + if eps: + vod["vod_play_from"], vod["vod_play_url"] = "播放列表", "#".join(eps) + return {"list": [vod]} + + play_list = [] + if mid := re.search(r'/(song|mp3|radio|radiolist|radioplay)/([^/]+)\.html', url): + sid = mid.group(2) + if pu := self._api("/js/play.php", data={"id": sid, "type": "music"}, method="POST", referer=url): + play_list.append(f"播放${self.e64('0@@@@'+pu)}") + lrc = f"{self.host}/plug/down.php?ac=music&lk=lrc&id={sid}" + play_list.append(f"歌词${self.e64('0@@@@'+lrc)}") + + elif vid := re.search(r'/(video|mp4)/([^/]+)\.html', url): + tasks = [] + with ThreadPoolExecutor(max_workers=3) as executor: + futures = {executor.submit(self._api, "/plug/down.php", None, {"ac": "vplay", "id": vid.group(2), "q": q}, "GET", url): n for n, q in [("蓝光", 1080), ("超清", 720), ("高清", 480)]} + for f in as_completed(futures): + if u := f.result(): + name = futures[f] + play_list.append(f"{name}${self.e64('0@@@@'+u)}") + play_list.sort(key=lambda x: {"蓝":0, "超":1, "高":2}.get(x[0], 3)) + + vod["vod_play_url"] = "#".join(play_list) if play_list else f"解析失败${self.e64('1@@@@'+url)}" + return {"list": [vod]} + + def _fetch_eps(self, url): + return self._get_eps(self.getpq(url)) + + def _get_eps(self, doc): + local_eps = [] + for li in doc(".play_list li, .song_list li, .music_list li").items(): + href = li("a").attr("href") + if not href or not re.search(r'/(song|mp3|radio|radiolist|radioplay)/', href): continue + song_name = self._clean(li("a").eq(0).text() or li(".name").text()) + local_eps.append(f"{song_name}${self.e64('1@@@@'+self._abs(href))}") + return local_eps + + def playerContent(self, flag, id, vipFlags): + url = self.d64(id).split("@@@@")[-1].replace(r"\/", "/") + if ".html" in url and not self.isVideoFormat(url): + if mid := re.search(r'/(song|mp3|radio|radiolist|radioplay)/([^/]+)\.html', url): + url = self._api("/js/play.php", data={"id": mid.group(2), "type": "music"}, method="POST", referer=url) or url + + elif vid := re.search(r'/(video|mp4)/([^/]+)\.html', url): + with ThreadPoolExecutor(max_workers=3) as executor: + futures = [executor.submit(self._api, "/plug/down.php", None, {"ac": "vplay", "id": vid.group(2), "q": q}, "GET", url) for q in [1080, 720, 480]] + for f in as_completed(futures): + if v_url := f.result(): + url = v_url + executor.shutdown(wait=False) + break + return {"parse": 0, "url": url, "header": {"User-Agent": self.headers["User-Agent"]}} + + def localProxy(self, param): + if param.get("type") == "img": + try: + r = self.session.get(param["url"], headers={"Referer": "https://www.2t58.com/"}, timeout=5) + if r.status_code == 200: return [200, r.headers.get("Content-Type", "image/jpeg"), r.content, {}] + except: pass + return None + + def _parse_list(self, items, tid=""): + res = [] + for li in items.items(): + a = li("a").eq(0) + href = a.attr("href") + if not href or href == "/" or any(x in href for x in ["/user/", "/login/", "javascript"]): continue + name = self._clean(li(".name").text() or a.attr("title") or a.text()) + if not name: continue + + img = li("img").attr("src") or "" + if img: + img = self._abs(img.replace('120', '500')) + pic = f"{self.getProxyUrl()}&url={img}&type=img" + else: pic = "" + + url = self._abs(href) + is_singer = "/singerlist/" in tid and "/singer/" in url + style = {"type": "oval"} if is_singer else ({"type": "list"} if any(x in tid for x in ["/list/", "/playtype/", "/albumlist/"]) else {"type": "rect", "ratio": 1.33}) + res.append({"vod_id": url, "vod_name": name, "vod_pic": pic, "vod_tag": "", "style": style}) + return res + + def _clean(self, text): + return re.sub(r'(爱听音乐网|视频下载说明|视频下载地址|www\.2t58\.com|MP3免费下载|LRC歌词下载|全部歌曲|\[第\d+页\]|刷新|每日推荐|最新|热门|推荐|MV|高清|无损)', '', text, flags=re.I).strip() + + def _fetch_filters(self, url): + doc = self.getpq(url) + selectors = [".ilingku_fl", ".class_list", ".screen_list", ".box_list", ".nav_list"] + if not (groups := [doc(s) for s in selectors if doc(s)]): return [] + + filters = [] + for i, group in enumerate(groups): + opts = [{"n": "全部", "v": "top" if "top" in url else "index"}] + seen = {opts[0]['v']} + for a in group("a").items(): + href = a.attr("href") + if not href: continue + v = href.split("?")[0].rstrip('/').split('/')[-1].replace('.html','') + if v not in seen: + opts.append({"n": a.text().strip(), "v": v}) + seen.add(v) + if len(opts) > 1: filters.append({"key": f"id{i}" if i else "id", "name": "分类", "value": opts}) + return filters + + def _api(self, path, data=None, params=None, method="GET", referer=None): + try: + h = self.headers.copy() + if referer: h["Referer"] = referer + func = self.session.post if method == "POST" else self.session.get + r = func(self.host + path, data=data, params=params, headers=h, timeout=3, allow_redirects=False) + if r.status_code in [301, 302] and r.headers.get("Location"): return self._abs(r.headers.get("Location").strip()) + try: + if u := r.json().get("url"): return self._abs(u.strip().replace(r"\/", "/")) + except: pass + if r.text.strip().startswith("http"): return r.text.strip() + except: pass + return "" + + def getpq(self, url): + import time + for _ in range(2): + try: return pq(self.session.get(self._abs(url), timeout=5).text) + except: time.sleep(0.1) + return pq("") + + def _abs(self, url): return url if url.startswith("http") else (f"http:{url}" if url.startswith("//") else f"{self.host}{'/' if not url.startswith('/') else ''}{url}") if url else "" + def e64(self, text): return b64encode(text.encode("utf-8")).decode("utf-8") + def d64(self, text): return b64decode(text.encode("utf-8")).decode("utf-8") \ No newline at end of file diff --git "a/spider/py/\347\210\261\347\216\251\351\237\263\344\271\220[\345\220\254].py" "b/spider/py/\347\210\261\347\216\251\351\237\263\344\271\220[\345\220\254].py" new file mode 100644 index 00000000..a703a59c --- /dev/null +++ "b/spider/py/\347\210\261\347\216\251\351\237\263\344\271\220[\345\220\254].py" @@ -0,0 +1,259 @@ +""" +@header({ + searchable: 1, + filterable: 1, + quickSearch: 1, + title: '爱玩音乐', + lang: 'hipy' +}) +""" + +import re +import sys +from base64 import b64encode, b64decode +from urllib.parse import quote +from pyquery import PyQuery as pq +from requests import Session, adapters +from urllib3.util.retry import Retry +from concurrent.futures import ThreadPoolExecutor, as_completed +sys.path.append('..') +from base.spider import Spider + +class Spider(Spider): + def init(self, extend=""): + self.host = "http://www.22a5.com" + self.session = Session() + retries = Retry(total=2, backoff_factor=0.5, status_forcelist=[429, 500, 502, 503, 504]) + adapter = adapters.HTTPAdapter(max_retries=retries, pool_connections=20, pool_maxsize=50) + self.session.mount("http://", adapter) + self.session.mount("https://", adapter) + self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36"} + self.session.headers.update(self.headers) + + def getName(self): return "爱玩音乐" + def isVideoFormat(self, url): return bool(re.search(r'\.(m3u8|mp4|mp3|m4a|flv)(\?|$)', url or "", re.I)) + def manualVideoCheck(self): return False + def destroy(self): self.session.close() + + def homeContent(self, filter): + classes = [ + {"type_name": "电台", "type_id": "/radiolist/index.html"}, + {"type_name": "歌单", "type_id": "/playtype/index.html"}, + {"type_name": "专辑", "type_id": "/albumlist/index.html"}, + {"type_name": "歌手", "type_id": "/singerlist/index/index/index/index.html"}, + {"type_name": "高清MV", "type_id": "/mvlist/oumei.html"}, + {"type_name": "新歌榜", "type_id": "/list/new.html"}, + {"type_name": "TOP榜单", "type_id": "/list/top.html"} + ] + filters = {} + + fetch_targets = ["/list/new.html", "/list/top.html", "/mvlist/index.html", "/playtype/index.html", "/albumlist/index.html", "/radiolist/index.html"] + for path in fetch_targets: + if f_data := self._fetch_filters(path): + filters[path] = f_data + + if "/radiolist/index.html" not in filters: + filters["/radiolist/index.html"] = [ + {"key": "id", "name": "分类", "value": [ + {"n": "最新", "v": "index"}, {"n": "最热", "v": "hot"}, {"n": "有声小说", "v": "novel"}, + {"n": "相声", "v": "xiangyi"}, {"n": "音乐", "v": "music"}, {"n": "情感", "v": "emotion"}, + {"n": "国漫", "v": "game"}, {"n": "影视", "v": "yingshi"}, {"n": "脱口秀", "v": "talkshow"}, + {"n": "历史", "v": "history"}, {"n": "儿童", "v": "children"}, {"n": "教育", "v": "education"}, + {"n": "八卦", "v": "gossip"}, {"n": "推理", "v": "tuili"}, {"n": "头条", "v": "headline"} + ]} + ] + + filters["/singerlist/index/index/index/index.html"] = [ + {"key": "area", "name": "地区", "value": [{"n": "全部", "v": "index"}, {"n": "华语", "v": "huayu"}, {"n": "欧美", "v": "oumei"}, {"n": "韩国", "v": "hanguo"}, {"n": "日本", "v": "ribrn"}]}, + {"key": "sex", "name": "性别", "value": [{"n": "全部", "v": "index"}, {"n": "男", "v": "male"}, {"n": "女", "v": "girl"}, {"n": "组合", "v": "band"}]}, + {"key": "genre", "name": "流派", "value": [{"n": n, "v": v} for n, v in [("全部","index"),("流行","liuxing"),("电子","dianzi"),("摇滚","yaogun"),("嘻哈","xiha"),("R&B","rb"),("民谣","minyao"),("爵士","jueshi"),("古典","gudian")]]}, + {"key": "char", "name": "字母", "value": [{"n": "全部", "v": "index"}] + [{"n": chr(i), "v": chr(i).lower()} for i in range(65, 91)]} + ] + return {"class": classes, "filters": filters, "list": []} + + def homeVideoContent(self): return {"list": []} + + def categoryContent(self, tid, pg, filter, extend): + pg = int(pg or 1) + url = tid + if "/singerlist/" in tid: + p = tid.split('/') + if len(p) >= 6: + p[2], p[3], p[4] = extend.get("area", p[2]), extend.get("sex", p[3]), extend.get("genre", p[4]) + p[-1] = f"{extend.get('char', 'index')}.html" + url = "/".join(p) + elif "id" in extend and extend["id"] not in ["index", "top"]: + url = tid.replace("index.html", f"{extend['id']}.html").replace("top.html", f"{extend['id']}.html") + if url == tid: url = f"{tid.rsplit('/', 1)[0]}/{extend['id']}.html" + + if pg > 1: + url = re.sub(r'/\d+\.html$', '.html', url) + url = re.sub(r'_\d+\.html$', '.html', url) + + if "/singerlist/" in url or "/radiolist/" in url or "/mvlist/" in url or "/playtype/" in url or "/list/" in url: + url = url.replace(".html", f"/{pg}.html") + else: + url = url.replace(".html", f"_{pg}.html") + + doc = self.getpq(url) + items = doc(".play_list li, .video_list li, .pic_list li, .singer_list li, .ali li, .layui-row li") or doc(".base_l li") + return {"list": self._parse_list(items, tid), "page": pg, "pagecount": 9999, "limit": 90, "total": 999999} + + def searchContent(self, key, quick, pg="1"): + return {"list": self._parse_list(self.getpq(f"/so/{quote(key)}/{pg}.html")(".base_l li, .play_list li"), "search"), "page": int(pg)} + + def detailContent(self, ids): + url = self._abs(ids[0]) + doc = self.getpq(url) + title = self._clean(doc("h1").text() or doc("title").text() or "") + pic = self._abs(doc(".djpg img, .pic img, .djpic img").attr("src")) + vod = {"vod_id": url, "vod_name": title, "vod_pic": pic, "vod_play_from": "爱玩音乐", "vod_content": ""} + + if any(x in url for x in ["/playlist/", "/album/", "/list/", "/singer/", "/special/", "/radio/", "/radiolist/"]): + eps = self._get_eps(doc) + page_urls = set() + for a in doc(".page a, .dede_pages a, .pagelist a").items(): + href = a.attr("href") + if href and not href.startswith("javascript") and href != "#": + abs_url = self._abs(href) + if abs_url != url: + page_urls.add(abs_url) + + if page_urls: + sorted_urls = sorted(list(page_urls), key=lambda x: int(re.search(r'[_\/](\d+)\.html', x).group(1)) if re.search(r'[_\/](\d+)\.html', x) else 0) + with ThreadPoolExecutor(max_workers=5) as executor: + futures = [executor.submit(self._fetch_eps, u) for u in sorted_urls] + for f in futures: + try: + if more_eps := f.result(): + eps.extend(more_eps) + except: pass + + if eps: + vod["vod_play_from"], vod["vod_play_url"] = "播放列表", "#".join(eps) + return {"list": [vod]} + + play_list = [] + if mid := re.search(r'/(song|mp3|radio|radiolist|radioplay)/([^/]+)\.html', url): + sid = mid.group(2) + if pu := self._api("/js/play.php", data={"id": sid, "type": "music"}, method="POST", referer=url): + play_list.append(f"播放${self.e64('0@@@@'+pu)}") + lrc = f"{self.host}/plug/down.php?ac=music&lk=lrc&id={sid}" + play_list.append(f"歌词${self.e64('0@@@@'+lrc)}") + + elif vid := re.search(r'/(video|mp4)/([^/]+)\.html', url): + tasks = [] + with ThreadPoolExecutor(max_workers=3) as executor: + futures = {executor.submit(self._api, "/plug/down.php", None, {"ac": "vplay", "id": vid.group(2), "q": q}, "GET", url): n for n, q in [("蓝光", 1080), ("超清", 720), ("高清", 480)]} + for f in as_completed(futures): + if u := f.result(): + name = futures[f] + play_list.append(f"{name}${self.e64('0@@@@'+u)}") + play_list.sort(key=lambda x: {"蓝":0, "超":1, "高":2}.get(x[0], 3)) + + vod["vod_play_url"] = "#".join(play_list) if play_list else f"解析失败${self.e64('1@@@@'+url)}" + return {"list": [vod]} + + def _fetch_eps(self, url): + return self._get_eps(self.getpq(url)) + + def _get_eps(self, doc): + local_eps = [] + for li in doc(".play_list li, .song_list li, .music_list li").items(): + href = li("a").attr("href") + if not href or not re.search(r'/(song|mp3|radio|radiolist|radioplay)/', href): continue + song_name = self._clean(li("a").eq(0).text() or li(".name").text()) + local_eps.append(f"{song_name}${self.e64('1@@@@'+self._abs(href))}") + return local_eps + + def playerContent(self, flag, id, vipFlags): + url = self.d64(id).split("@@@@")[-1].replace(r"\/", "/") + if ".html" in url and not self.isVideoFormat(url): + if mid := re.search(r'/(song|mp3|radio|radiolist|radioplay)/([^/]+)\.html', url): + url = self._api("/js/play.php", data={"id": mid.group(2), "type": "music"}, method="POST", referer=url) or url + + elif vid := re.search(r'/(video|mp4)/([^/]+)\.html', url): + with ThreadPoolExecutor(max_workers=3) as executor: + futures = [executor.submit(self._api, "/plug/down.php", None, {"ac": "vplay", "id": vid.group(2), "q": q}, "GET", url) for q in [1080, 720, 480]] + for f in as_completed(futures): + if v_url := f.result(): + url = v_url + executor.shutdown(wait=False) + break + return {"parse": 0, "url": url, "header": {"User-Agent": self.headers["User-Agent"]}} + + def localProxy(self, param): + if param.get("type") == "img": + try: + r = self.session.get(param["url"], headers={"Referer": "https://www.2t58.com/"}, timeout=5) + if r.status_code == 200: return [200, r.headers.get("Content-Type", "image/jpeg"), r.content, {}] + except: pass + return None + + def _parse_list(self, items, tid=""): + res = [] + for li in items.items(): + a = li("a").eq(0) + href = a.attr("href") + if not href or href == "/" or any(x in href for x in ["/user/", "/login/", "javascript"]): continue + name = self._clean(li(".name").text() or a.attr("title") or a.text()) + if not name: continue + + img = li("img").attr("src") or "" + if img: + img = self._abs(img.replace('120', '500')) + pic = f"{self.getProxyUrl()}&url={img}&type=img" + else: pic = "" + + url = self._abs(href) + is_singer = "/singerlist/" in tid and "/singer/" in url + style = {"type": "oval"} if is_singer else ({"type": "list"} if any(x in tid for x in ["/list/", "/playtype/", "/albumlist/"]) else {"type": "rect", "ratio": 1.33}) + res.append({"vod_id": url, "vod_name": name, "vod_pic": pic, "vod_tag": "", "style": style}) + return res + + def _clean(self, text): + return re.sub(r'(爱玩音乐网|视频下载说明|视频下载地址|www\.2t58\.com|MP3免费下载|LRC歌词下载|全部歌曲|\[第\d+页\]|刷新|每日推荐|最新|热门|推荐|MV|高清|无损)', '', text, flags=re.I).strip() + + def _fetch_filters(self, url): + doc = self.getpq(url) + selectors = [".ilingku_fl", ".class_list", ".screen_list", ".box_list", ".nav_list"] + if not (groups := [doc(s) for s in selectors if doc(s)]): return [] + + filters = [] + for i, group in enumerate(groups): + opts = [{"n": "全部", "v": "top" if "top" in url else "index"}] + seen = {opts[0]['v']} + for a in group("a").items(): + href = a.attr("href") + if not href: continue + v = href.split("?")[0].rstrip('/').split('/')[-1].replace('.html','') + if v not in seen: + opts.append({"n": a.text().strip(), "v": v}) + seen.add(v) + if len(opts) > 1: filters.append({"key": f"id{i}" if i else "id", "name": "分类", "value": opts}) + return filters + + def _api(self, path, data=None, params=None, method="GET", referer=None): + try: + h = self.headers.copy() + if referer: h["Referer"] = referer + func = self.session.post if method == "POST" else self.session.get + r = func(self.host + path, data=data, params=params, headers=h, timeout=3, allow_redirects=False) + if r.status_code in [301, 302] and r.headers.get("Location"): return self._abs(r.headers.get("Location").strip()) + try: + if u := r.json().get("url"): return self._abs(u.strip().replace(r"\/", "/")) + except: pass + if r.text.strip().startswith("http"): return r.text.strip() + except: pass + return "" + + def getpq(self, url): + import time + for _ in range(2): + try: return pq(self.session.get(self._abs(url), timeout=5).text) + except: time.sleep(0.1) + return pq("") + + def _abs(self, url): return url if url.startswith("http") else (f"http:{url}" if url.startswith("//") else f"{self.host}{'/' if not url.startswith('/') else ''}{url}") if url else "" + def e64(self, text): return b64encode(text.encode("utf-8")).decode("utf-8") + def d64(self, text): return b64decode(text.encode("utf-8")).decode("utf-8") \ No newline at end of file From d1518cb70ec0bcac91da77d862cca118c15c3590 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Wed, 14 Jan 2026 20:09:46 +0800 Subject: [PATCH 013/101] =?UTF-8?q?=E5=88=A0=E9=99=A4DJ=E9=9F=B3=E4=B9=90[?= =?UTF-8?q?=E5=90=AC].js=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\351\237\263\344\271\220[\345\220\254].js" | 47 ------------------- 1 file changed, 47 deletions(-) delete mode 100644 "spider/js_dr2/DJ\351\237\263\344\271\220[\345\220\254].js" diff --git "a/spider/js_dr2/DJ\351\237\263\344\271\220[\345\220\254].js" "b/spider/js_dr2/DJ\351\237\263\344\271\220[\345\220\254].js" deleted file mode 100644 index 3a9dc395..00000000 --- "a/spider/js_dr2/DJ\351\237\263\344\271\220[\345\220\254].js" +++ /dev/null @@ -1,47 +0,0 @@ -/* -@header({ - searchable: 2, - filterable: 0, - quickSearch: 0, - title: 'DJ音乐', - '类型': '影视', - lang: 'dr2' -}) -*/ - -// 道长 drpy仓库 https://gitcode.net/qq_32394351/dr_py -// 道长 drpy安卓本地搭建说明 https://code.gitlink.org.cn/api/v1/repos/hjdhnx/dr_py/blob/master/%E5%AE%89%E5%8D%93%E6%9C%AC%E5%9C%B0%E6%90%AD%E5%BB%BA%E8%AF%B4%E6%98%8E.md -// 道长 drpy写源 模板规则说明 https://gitcode.net/supertlo/dr_py#%E6%A8%A1%E6%9D%BF%E8%A7%84%E5%88%99%E8%AF%B4%E6%98%8E -// 道长 drpy写源 套模模版 https://ghproxy.net/https://raw.githubusercontent.com/hjdhnx/dr_py/main/js/%E6%A8%A1%E6%9D%BF.js -// 道长 drpy写源 影片教程 http://101.34.67.237:5244/%E6%95%99%E8%82%B2/drpy -// 道长 drpy写源 影片教程(m3u8切片) https://freedrpy.run.goorm.io/txt/jc/playlist.m3u8 -// 海阔下载 https://haikuo.lanzoui.com/u/GoldRiver -// Pluto Player官方TG https://t.me/PlutoPlayer -// Pluto Player官方TG https://t.me/PlutoPlayerChannel - -// pluto 播放正常 -// 俊老的壳或PythonBox 在rules新增底下设定 即可正常播放 -// {"host":"www.djuu.com","rule":["mp4.djuu.com"]}, - -var rule = { - title:'DJ音乐', - host:'http://www.djuu.com', - homeUrl:'/exclusive/115_1.html',//网站的首页链接,可以是完整路径或者相对路径,用于分类获取和推荐获取 fyclass是分类标签 fypage是页数 - url:'/djlist/fyclass_fypage.html', - searchUrl:'/search?musicname=**', - searchable:2, - quickSearch:0, - class_parse:'#top_banner_bg div;a&&Text;a&&href;/djlist/(\\d+)_1.html', - headers:{ - 'User-Agent':'PC_UA' - }, - timeout:5000, - play_parse:true, - lazy:'', - limit:6, - double:false, - 推荐:'*', - 一级:'.list_musiclist tr:gt(0);a&&title;img&&src;.cor999:eq(1)&&Text;a&&href', - 二级:'*', - 搜索:'*;*;*;.sc_1&&Text;*', -} From 6fe76983811e2d976a021ff66e6d7d715ba8f027 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Wed, 14 Jan 2026 20:27:17 +0800 Subject: [PATCH 014/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0config/map.txt?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/map.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/map.txt b/config/map.txt index 756117df..1d3a929f 100644 --- a/config/map.txt +++ b/config/map.txt @@ -30,9 +30,14 @@ UC分享@@?type=url¶ms=../json/UC分享.json@@UC分享[盘] 网盘[模板]@@?type=url¶ms=../json/域名配置.json$欧歌@@欧歌ᵐ[盘] 网盘[模板]@@?type=url¶ms=../json/域名配置.json$至臻@@至臻ᵐ[盘] AppFox@@http://app.hktvyb.cc@@TVB云播[AFX] +AppFox@@{"host":"http://www.yezitv.top/dtym.json"}@@木瓜影视[AFX] +AppFox@@{"host":"http://nico.oiio.fun"}@@花柳影视[AFX] AppFox@@{"host":"https://cunchu8.obs.cn-north-4.myhuaweicloud.com/config.json","parse":{"JL4K":"http://194.147.100.155:7891/?url="}}@@火猫影视[AFX] AppFei@@https://ysc.yy-fun.cc/feiapp@@呀哩4K[AF] AppFei@@https://ysa.yy-fun.cc/feiapp@@森林动漫[AF] +AppGet@@{"host":"https://snysw.xyz/mf4kzs327.txt","key":"1234567887654321"}@@魔方[AG¹] +AppGet@@{"host":"https://gitee.com/wmmoliill/wimg/raw/master/img/bk/9.txt","key":"88689667dce61725"}@@茉莉[AG¹] +AppGet@@{"host":"http://ys.qist.top","key":"2SWSPFxugBLPPOKo"}@@旗星[AG¹] AppGet@@{"host":"https://api1.bffree.cn","key":"2015692015692015"}@@橘子[AG¹] AppGet@@{"host":"https://dy.58ys.vip","key":"JEWibY1AgWF0V1xx"}@@五八[AG¹] AppGet@@{"host":"https://mac.555618.xyz","key":"#getapp@TMD@2025"}@@玲珑[AG¹] From 4d0472c88379c014f72d3a0adfbedd115e22d2f9 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Wed, 14 Jan 2026 20:42:47 +0800 Subject: [PATCH 015/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0config/map.txt?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/map.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/config/map.txt b/config/map.txt index 1d3a929f..a6603726 100644 --- a/config/map.txt +++ b/config/map.txt @@ -57,6 +57,7 @@ AppV2²@@http://38.47.213.61:41271@@闪影[AV²] AppV2²@@http://v.lnhaozhenjin.cn@@好震惊[AV²] AppV2²@@http://jxfmax.juxiafan.com@@剧下饭[AV²] AppV1@@http://ziyuncms.feifan12.xyz/api.php@@紫云[AV¹] +getapp3.4.4@@{"host":"https://staraugust123456.oss-cn-hangzhou.aliyuncs.com/2.txt","datakey":"staraugust123456","api":2}@@云云[AG³] getapp3.4.4@@{"host":"https://jingyu4k-1312635929.cos.ap-nanjing.myqcloud.com/1.json","datakey":"AAdgrdghjfgswerA","api":2}@@鲸鱼影视[AG³] getapp3.4.4@@{"host":"https://www.guahd.com/1.txt","key":"f2A7D4B9E8C16531"}@@瓜萌[AG³] getapp3.4.4@@{"host":"https://99.jl8.top/1.txt","key":"xnybssspqtwotuwj"}@@七月[AG³] From 9740269e788c5dd36aab35cc787133574d9e7488 Mon Sep 17 00:00:00 2001 From: Taois Date: Wed, 14 Jan 2026 23:44:11 +0800 Subject: [PATCH 016/101] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=87=A0?= =?UTF-8?q?=E4=B8=AA=E9=9F=B3=E4=B9=90=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\345\212\250\346\274\253[\346\274\253].js" | 9 ++- ...\351\237\263\344\271\220[\345\220\254].js" | 45 ++++++----- ...45\225\212\345\223\210DJ[\345\220\254].js" | 10 ++- ...\347\243\201\345\234\272[\345\220\254].js" | 78 ++++++++++--------- ...\345\220\254\344\271\246[\345\220\254].js" | 57 ++++++++------ 5 files changed, 121 insertions(+), 78 deletions(-) diff --git "a/spider/catvod/\345\227\267\345\221\234\345\212\250\346\274\253[\346\274\253].js" "b/spider/catvod/\345\227\267\345\221\234\345\212\250\346\274\253[\346\274\253].js" index e11949df..9f9ded18 100644 --- "a/spider/catvod/\345\227\267\345\221\234\345\212\250\346\274\253[\346\274\253].js" +++ "b/spider/catvod/\345\227\267\345\221\234\345\212\250\346\274\253[\346\274\253].js" @@ -4,7 +4,14 @@ title: '嗷呜动漫', author: '小可乐/v6.1.1' "ext": { "host": "xxxx", //站点网址 "timeout": 6000 //请求超时,单位毫秒 -} +} +@header({ + searchable: 1, + filterable: 1, + quickSearch: 1, + title: '嗷呜动漫[漫]', + lang: 'cat' +}) */ import {Crypto} from 'assets://js/lib/cat.js'; diff --git "a/spider/js/DJ\351\237\263\344\271\220[\345\220\254].js" "b/spider/js/DJ\351\237\263\344\271\220[\345\220\254].js" index 8b7f56e7..f5266a62 100644 --- "a/spider/js/DJ\351\237\263\344\271\220[\345\220\254].js" +++ "b/spider/js/DJ\351\237\263\344\271\220[\345\220\254].js" @@ -12,31 +12,40 @@ */ var rule = { - title:'DJ音乐', - host:'http://www.djuu.com', - homeUrl:'/exclusive/115_1.html', - url:'/djlist/fyclass_fypage.html', - searchUrl:'/search?musicname=**', + title: 'DJ音乐', + host: 'http://www.djuu.com', + homeUrl: '/exclusive/115_1.html', + url: '/djlist/fyclass_fypage.html', + searchUrl: '/search?musicname=**', author: 'EylinSir', logo: 'https://pic.289.com/up/2023-12/20231219154340126.png', hikerListCol: 'icon_4', - searchable:2, - quickSearch:0, + searchable: 2, + quickSearch: 0, class_name: '迪高串烧&慢摇串烧&慢歌串烧&中文Remix&外文Remix&HOUSE&HOUSE&霓虹风格&Mashup&中文DISCO&外文DISCO', class_url: '1&2&3&4&5&6&7&8&9&10', - headers:{ - 'User-Agent':'PC_UA' + headers: { + 'User-Agent': 'PC_UA' }, - timeout:5000, - limit:6, - double:false, - play_parse:true, - lazy: async function() { + timeout: 5000, + limit: 6, + double: false, + play_parse: true, + lazy: async function () { let {input} = this; + log("input:", input); + let html = await request(input); + // log(html) + let music = html.match(/var\s+music\s*=\s*(\{[\s\S]*?\})/)[1]; + music = JSON5.parse(music); + // log(music); + // 算法来自:https://www.djuu.com/static/js/common.js + input = urljoin(input, "//mp4.djuu.com/" + music.file + ".m4a"); + // log(input); return input; }, - 推荐:'*', - 一级:'.list_musiclist tr:gt(0);a&&title;img&&src;.cor999:eq(1)&&Text;a&&href', - 二级:'*', - 搜索:'*;*;*;.sc_1&&Text;*', + 推荐: '*', + 一级: '.list_musiclist tr:gt(0);a&&title;img&&src;.cor999:eq(1)&&Text;a&&href', + 二级: '*', + 搜索: '*;*;*;.sc_1&&Text;*', } diff --git "a/spider/js/\345\225\212\345\223\210DJ[\345\220\254].js" "b/spider/js/\345\225\212\345\223\210DJ[\345\220\254].js" index a1bc9e9b..f77ee4ba 100644 --- "a/spider/js/\345\225\212\345\223\210DJ[\345\220\254].js" +++ "b/spider/js/\345\225\212\345\223\210DJ[\345\220\254].js" @@ -28,7 +28,15 @@ var rule = { // console.log('input:', input); let html = await request(input); let _url = pdfh(html, 'video&&source&&src'); - return {parse: 0, url: _url, js: ''}; + return { + parse: 0, + url: _url, + js: '', + header: { + referer: 'https://m.ahadj.com/', + 'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Mobile Safari/537.36' + } + }; }, 推荐: '*', searchUrl: '/search/?key=**&page=fypage.html', diff --git "a/spider/js/\351\237\263\344\271\220\347\243\201\345\234\272[\345\220\254].js" "b/spider/js/\351\237\263\344\271\220\347\243\201\345\234\272[\345\220\254].js" index bab53c50..a333be94 100755 --- "a/spider/js/\351\237\263\344\271\220\347\243\201\345\234\272[\345\220\254].js" +++ "b/spider/js/\351\237\263\344\271\220\347\243\201\345\234\272[\345\220\254].js" @@ -10,45 +10,51 @@ */ var rule = { - title: '音乐磁场', - host: 'https://hifini.net/', - url: '/forum-fyclass-fypage.htm?orderby=lastpid&follow=0', - searchUrl: '/search-**-1-0-fypage.htm', - class_parse: '.navbar-nav li;a&&Text;a&&href;forum-(.*/?).htm', - searchable: 2, - quickSearch: 0, - filterable: 0, - headers: { - 'User-Agent': 'MOBILE_UA', - }, - play_parse: true, - lazy: ` -let html = request(input); + title: '音乐磁场', + host: 'https://hifini.net/', + url: '/forum-fyclass-fypage.htm?orderby=lastpid&follow=0', + searchUrl: '/search-**-1-0-fypage.htm', + class_parse: '.navbar-nav li;a&&Text;a&&href;forum-(.*/?).htm', + searchable: 2, + quickSearch: 0, + filterable: 0, + headers: { + 'User-Agent': 'MOBILE_UA', + }, + play_parse: true, + lazy: $js.toString(async () => { + let html = await request(input); // 1️⃣ 直链 -let m = html.match(/url:\\s*"(https?:[^"]+)"/); -let playUrl = m ? m[1] : input; +// let m = html.match(/url:\s*"(https?:[^"]+)"/); +// let playUrl = m ? m[1] : input; + const urlPropertyPattern = /url\s*:\s*['"](https?:\/\/[^'"]+)['"]/gi; + const matches = [...html.matchAll(urlPropertyPattern)]; + const urlValues = matches.map(match => match[1]); + console.log(urlValues); + let playUrl = urlValues[0] || input; // 2️⃣ 歌词 -let lyric = []; -let ps = html.match(/

      (.*?)<\\/p>/g) || []; -for(let p of ps){ - let t = p.replace(/<[^>]+>/g,'').trim(); - if(!t) continue; - if(/下载链接|提取码|隐藏内容/.test(t)) break; - lyric.push(t); -} + let lyric = []; + let ps = html.match(/

      (.*?)<\/p>/g) || []; + for (let p of ps) { + let t = p.replace(/<[^>]+>/g, '').trim(); + if (!t) continue; + if (/下载链接|提取码|隐藏内容/.test(t)) break; + lyric.push(t); + } -input = { - parse: 0, - url: playUrl, - lyric: lyric.join('\\n') -}; -`, - limit: 6, - double: true, - 推荐: '.cbox_list;*;*;*;*;*', - 一级: 'ul.list-unstyled li:gt(2);.subject&&Text;img&&src;.media-body&&Text;.subject a&&href', - 二级: '*', - 搜索: '*', + input = { + parse: 0, + url: playUrl, + lyric: lyric.join('\n') + }; + return input + }), + limit: 6, + double: true, + 推荐: '.cbox_list;*;*;*;*;*', + 一级: 'ul.list-unstyled li:gt(2);.subject&&Text;img&&src;.media-body&&Text;.subject a&&href', + 二级: '*', + 搜索: '*', } diff --git "a/spider/js_dr2/\347\210\261\344\270\212\345\220\254\344\271\246[\345\220\254].js" "b/spider/js_dr2/\347\210\261\344\270\212\345\220\254\344\271\246[\345\220\254].js" index 2a00a53e..40ee8ad7 100644 --- "a/spider/js_dr2/\347\210\261\344\270\212\345\220\254\344\271\246[\345\220\254].js" +++ "b/spider/js_dr2/\347\210\261\344\270\212\345\220\254\344\271\246[\345\220\254].js" @@ -10,29 +10,42 @@ */ var rule = { - title:'爱上你听书网', - host:'https://www.230ts.net', - url:'/sort/fyclass/fypage.html', - searchUrl:'/search.html?searchtype=name&searchword=**&page=fypage', - searchable:2, - quickSearch:0, - headers:{ - 'User-Agent':'PC_UA' + title: '爱上你听书网', + host: 'https://www.230ts.net', + url: '/sort/fyclass/fypage.html', + searchUrl: '/search.html?searchtype=name&searchword=**&page=fypage', + searchable: 2, + quickSearch: 0, + headers: { + 'User-Agent': 'PC_UA' }, - timeout:5000, + timeout: 5000, class_parse: '.nav-ol&&li:gt(0):lt(6);a&&Text;a&&href;.*/(\\w+).html', - play_parse:true, - lazy:'js:input=input.replace("www","wap")', - limit:6, - 推荐:'#myTab_Content1&&li;.tab-book-title&&Text;*;.tab-book-author&&Text;*', - 一级:'ul.list-works&&li;.list-book-dt--span&&Text;.lazy&&data-original;.book-author:eq(2)&&a&&Text;a&&href', - 二级:{ - title:'.book-cover&&alt;.book-info&&dd--span:eq(1)&&Text', - img:'.book-cover&&src', - desc:'.book-info&&dd:eq(4)&&Text;;;.book-info&&dd--span:eq(3)&&Text;.book-info&&dd--span:eq(2)&&Text', - content:'.book-des&&Text', - tabs:'.playlist-top&&h2', - lists:'#playlist:eq(#id)&&li', + play_parse: true, + lazy: $js.toString(() => { + let html = request(input); + let src = pd(html, 'iframe#play&&src', input); + log('src:' + src); + html = request(src); + const regex = /mp3\s*:\s*'([^']+)'/; + const match = html.match(regex); + if (match && match[1].includes('auth_key')) { + // 替换变量部分为 .mp3. + src = match[1].replace(/'([^']*)'\s*\+\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\+\s*'([^']*)'/, '$1.mp3.$2'); + log('match src:' + src); + } + input = src + }), + limit: 6, + 推荐: '#myTab_Content1&&li;.tab-book-title&&Text;*;.tab-book-author&&Text;*', + 一级: 'ul.list-works&&li;.list-book-dt--span&&Text;.lazy&&data-original;.book-author:eq(2)&&a&&Text;a&&href', + 二级: { + title: '.book-cover&&alt;.book-info&&dd--span:eq(1)&&Text', + img: '.book-cover&&src', + desc: '.book-info&&dd:eq(4)&&Text;;;.book-info&&dd--span:eq(3)&&Text;.book-info&&dd--span:eq(2)&&Text', + content: '.book-des&&Text', + tabs: '.playlist-top&&h2', + lists: '#playlist:eq(#id)&&li', }, - 搜索:'*', + 搜索: '*', } \ No newline at end of file From 0f351d6fa79defdfdfd7973c32be1aa5455a12a7 Mon Sep 17 00:00:00 2001 From: Taois Date: Thu, 15 Jan 2026 00:10:19 +0800 Subject: [PATCH 017/101] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=B0=8F?= =?UTF-8?q?=E8=AF=B4=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...04\345\260\217\350\257\264[\344\271\246].js" | 17 ++++++++++++----- ...71\345\260\217\350\257\264[\344\271\246].js" | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git "a/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" "b/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" index 644fe3f7..b659fa25 100644 --- "a/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" +++ "b/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" @@ -14,10 +14,14 @@ // http://localhost:5757/api/番茄小说[书]?wd=斩神&pg=2 // http://localhost:5757/api/番茄小说[书]?play=7432172914662720025&flag=番茄小说 +// 对接API:https://qkfqapi.vv9v.cn/docs +// https://github.com/POf-L/Fanqie-novel-Downloader/blob/main/novel_downloader.py + const {getRandomFromList} = $.require('./_lib.random.js'); const {requestHtml} = $.require('./_lib.request.js'); // const fqweb_host = 'http://fqweb.jsj66.com'; -const fqweb_host = 'http://fanqie.mduge.com'; +// const fqweb_host = 'http://fanqie.mduge.com'; +const fqweb_host = 'https://qkfqapi.vv9v.cn'; var rule = { 类型: '小说', @@ -26,7 +30,8 @@ var rule = { host: 'https://fanqienovel.com/', homeUrl: 'https://fanqienovel.com/api/author/book/category_list/v0/', url: '/api/author/library/book_list/v0/?page_count=18&page_index=(fypage-1)&gender=1&category_id=fyclass&creation_status=-1&word_count=-1&book_type=-1&sort=0#fyfilter', - searchUrl: fqweb_host + '/search?query=**&page=fypage', + // searchUrl: fqweb_host + '/search?query=**&page=fypage', + searchUrl: fqweb_host + '/api/search?key=**&tab_type=3&offset=0&page=fypage', searchable: 2, quickSearch: 0, filterable: 1, @@ -148,7 +153,7 @@ var rule = { }, searchHandel: function (json) { return { - data: json.data.search_tabs[0].data + data: json.data.search_tabs[5].data }; }, 搜索: async function (wd, quick, pg) { @@ -180,7 +185,8 @@ var rule = { let content_url = ''; // 正文获取接口 // content_url = `http://fqweb.jsj66.com/content?item_id=${input}`; // content_url = `https://fanqienovel.com/reader/${input}?enter_from=reader`; - content_url = `${fqweb_host}/content?item_id=${input}`; + // content_url = `${fqweb_host}/content?item_id=${input}`; + content_url = `${fqweb_host}/api/content?tab=小说&item_id=${input}`; /* log(content_url); @@ -200,7 +206,8 @@ var rule = { */ let json = JSON.parse(html); - content = json.content.replace(/\n\n妍󠇕希󠆖󠅽󠇕󠆨󠅼󠄡󠄩󠄠󠄩󠄣󠄣󠄢󠄨󠄨󠄩\n/g, "\n"); + // content = json.content.replace(/\n\n妍󠇕希󠆖󠅽󠇕󠆨󠅼󠄡󠄩󠄠󠄩󠄣󠄣󠄢󠄨󠄨󠄩\n/g, "\n"); + content = json.data.content; // print(content) let ret = JSON.stringify({ title, diff --git "a/spider/js/\351\241\266\347\202\271\345\260\217\350\257\264[\344\271\246].js" "b/spider/js/\351\241\266\347\202\271\345\260\217\350\257\264[\344\271\246].js" index 19305d76..99a113b4 100644 --- "a/spider/js/\351\241\266\347\202\271\345\260\217\350\257\264[\344\271\246].js" +++ "b/spider/js/\351\241\266\347\202\271\345\260\217\350\257\264[\344\271\246].js" @@ -26,7 +26,7 @@ var rule = { filter_url: '', filter_def: {}, headers: { - 'User-Agent': 'MOBILE_UA', + 'User-Agent': 'PC_UA', }, timeout: 5000, hikerListCol: "text_1", From b1b4452835ec21c1dd043b761a8dd590d2febb4a Mon Sep 17 00:00:00 2001 From: Taois Date: Thu, 15 Jan 2026 00:13:16 +0800 Subject: [PATCH 018/101] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ docs/updateRecord.md | 6 ++++++ package.json | 2 +- public/index.html | 2 ++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index da5f1e36..9e7990da 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,10 @@ nodejs作为服务端的drpy实现。全面升级异步写法 ## 更新记录 +### 20260115 + +更新至V1.3.17 + ### 20260113 更新至V1.3.16 diff --git a/docs/updateRecord.md b/docs/updateRecord.md index 6959904f..8fe8d811 100644 --- a/docs/updateRecord.md +++ b/docs/updateRecord.md @@ -1,5 +1,11 @@ # drpyS更新记录 +### 20260115 + +更新至V1.3.17 + +1. 新增一些源 & 修复一些源 + ### 20260113 更新至V1.3.16 diff --git a/package.json b/package.json index af0c9f5a..25b196bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "drpy-node", - "version": "1.3.16", + "version": "1.3.17", "main": "index.js", "type": "module", "scripts": { diff --git a/public/index.html b/public/index.html index 6b7fb650..796ff944 100644 --- a/public/index.html +++ b/public/index.html @@ -67,6 +67,8 @@

      免费壳子推荐

    • 皮卡丘

    更新记录

    +

    20260115

    +

    更新至V1.3.17

    20260113

    更新至V1.3.16

    20260112

    From 9c650c5374f8bb83777f4a37fd01d338f890138b Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Thu, 15 Jan 2026 10:53:05 +0800 Subject: [PATCH 019/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/map.txt | 3 +++ "spider/js/TG\346\220\234[\346\220\234].js" | 2 +- "spider/js/TG\347\233\230\346\220\234[\346\220\234].js" | 2 +- "spider/js/TG\351\242\221\351\201\223.js" | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/config/map.txt b/config/map.txt index a6603726..83951c69 100644 --- a/config/map.txt +++ b/config/map.txt @@ -43,6 +43,9 @@ AppGet@@{"host":"https://dy.58ys.vip","key":"JEWibY1AgWF0V1xx"}@@五八[AG¹] AppGet@@{"host":"https://mac.555618.xyz","key":"#getapp@TMD@2025"}@@玲珑[AG¹] AppGet@@{"host":"https://app.omofun1.top","key":"66dc309cbeeca454"}@@OMOfun[AG¹] AppGet@@{"host":"http://tv.yy-fun.cc","key":"qkxnwkfjwpcnwycl"}@@丫丫动漫[AG¹] +AppGet@@{"host":"https://www.cyfz.vip","key":"e72cdfd629e8895d"}@@方舟动漫[AG¹] +AppGet@@{"host":"http://cic.aicg.fun","key":"2c4h36abd96se10u"}@@元咲动漫[AG¹] +AppGet@@{"host":"https://www.gugu3.com","key":"nKfZ8KX6JTNWRzTD"}@@咕咕动漫[AG¹] AppSk@@{"host":"https://skyappdata-1321528676.cos.accelerate.myqcloud.com/4kapp/appipr.txt","key":"ygcnbckhcuvygdyb","iv":"4023892775143708"}@@即看影视[AS] AppSk@@{"host":"https://kankelm.cn:2024/appdomain.txt","key":"ygcnbcvybqqckwqy","iv":"1583560747143708"}@@看客联盟[AS] AppSk@@{"host":"https://dmsk.oss-rg-china-mainland.aliyuncs.com/dmapp/dmapi.txt","key":"ygcnbcobcegtgigg","iv":"4058263969143708"}@@2k动漫[AS] diff --git "a/spider/js/TG\346\220\234[\346\220\234].js" "b/spider/js/TG\346\220\234[\346\220\234].js" index 5d5ff90c..5a98a5cf 100755 --- "a/spider/js/TG\346\220\234[\346\220\234].js" +++ "b/spider/js/TG\346\220\234[\346\220\234].js" @@ -10,7 +10,7 @@ }) */ -const Pan_API = 'http://127.0.0.1:6080'; // 网盘链接有效性检测过滤api,需自行替换 +const Pan_API = 'https://pancheck.banye.tech:7777'; // 网盘链接有效性检测过滤api,需自行替换 const Pan_Sift = []; const DEFAULT_CHANNELS = 'douerpan,bdwpzhpd,wydwpzy,sgkwpzy,zyywpzy,Baidu_Netdisk,PanjClub,youxigs,yunpanuc,zyfb123,ysxb48,xiangnikanj';//定义频道 const DEFAULT_SOURCES = ['百度网盘', '夸克网盘', 'UC网盘', '移动云盘', '天翼云盘', '115网盘', '阿里云盘', '123云盘'];//定义搜索网盘类型及顺序 diff --git "a/spider/js/TG\347\233\230\346\220\234[\346\220\234].js" "b/spider/js/TG\347\233\230\346\220\234[\346\220\234].js" index 9ab16fb4..4629447e 100644 --- "a/spider/js/TG\347\233\230\346\220\234[\346\220\234].js" +++ "b/spider/js/TG\347\233\230\346\220\234[\346\220\234].js" @@ -10,7 +10,7 @@ }) */ -const Pan_API = 'http://127.0.0.1:6080'; // PanCheck的API地址 自行替换 +const Pan_API = 'https://pancheck.banye.tech:7777'; // PanCheck的API地址 自行替换 const Pan_So = 'https://so.252035.xyz'; // PanSou地址,自行替换 const PAN_TYPES = '百度网盘,夸克网盘,UC网盘,天翼云盘,移动云盘'; // 默认搜索的网盘类型和排序,逗号分隔 const MAX_RESULTS = 15; // 默认搜索结果数量 (每个网盘类型最多15条) diff --git "a/spider/js/TG\351\242\221\351\201\223.js" "b/spider/js/TG\351\242\221\351\201\223.js" index ffbbdd60..85011738 100755 --- "a/spider/js/TG\351\242\221\351\201\223.js" +++ "b/spider/js/TG\351\242\221\351\201\223.js" @@ -93,7 +93,7 @@ const rule = { host: 'https://t.me', url: '/s/fyclass', searchUrl: '?q=**', - Pan_API: 'http://127.0.0.1:6080', // 网盘链接有效性检测过滤api,需自行替换 + Pan_API: 'https://pancheck.banye.tech:7777', // 网盘链接有效性检测过滤api,需自行替换 logo: 'https://api.xinac.net/icon/?url=https://t.me', searchable: 1, quickSearch: 1, From 200a79cfbf2fe6ed903bfa3c7615a16563c5bf48 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Thu, 15 Jan 2026 10:54:43 +0800 Subject: [PATCH 020/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TG\351\242\221\351\201\223\351\205\215\347\275\256.json" | 4 ---- 1 file changed, 4 deletions(-) diff --git "a/json/TG\351\242\221\351\201\223\351\205\215\347\275\256.json" "b/json/TG\351\242\221\351\201\223\351\205\215\347\275\256.json" index 273f60a0..6cda37ec 100644 --- "a/json/TG\351\242\221\351\201\223\351\205\215\347\275\256.json" +++ "b/json/TG\351\242\221\351\201\223\351\205\215\347\275\256.json" @@ -23,10 +23,6 @@ "type_id": "yunpanuc", "type_name": "UC资源" }, - { - "type_id": "xiangnikanj", - "type_name": "短剧频道" - }, { "type_id": "PanjClub", "type_name": "盘酱酱Club" From 5383673e47d88bfe2b9cd7117ea97b11d25b26e6 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Thu, 15 Jan 2026 14:15:14 +0800 Subject: [PATCH 021/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/map.txt | 3 - ...\346\235\277\351\205\215\347\275\256.json" | 200 +++++++++++++++++- 2 files changed, 192 insertions(+), 11 deletions(-) diff --git a/config/map.txt b/config/map.txt index 83951c69..a6603726 100644 --- a/config/map.txt +++ b/config/map.txt @@ -43,9 +43,6 @@ AppGet@@{"host":"https://dy.58ys.vip","key":"JEWibY1AgWF0V1xx"}@@五八[AG¹] AppGet@@{"host":"https://mac.555618.xyz","key":"#getapp@TMD@2025"}@@玲珑[AG¹] AppGet@@{"host":"https://app.omofun1.top","key":"66dc309cbeeca454"}@@OMOfun[AG¹] AppGet@@{"host":"http://tv.yy-fun.cc","key":"qkxnwkfjwpcnwycl"}@@丫丫动漫[AG¹] -AppGet@@{"host":"https://www.cyfz.vip","key":"e72cdfd629e8895d"}@@方舟动漫[AG¹] -AppGet@@{"host":"http://cic.aicg.fun","key":"2c4h36abd96se10u"}@@元咲动漫[AG¹] -AppGet@@{"host":"https://www.gugu3.com","key":"nKfZ8KX6JTNWRzTD"}@@咕咕动漫[AG¹] AppSk@@{"host":"https://skyappdata-1321528676.cos.accelerate.myqcloud.com/4kapp/appipr.txt","key":"ygcnbckhcuvygdyb","iv":"4023892775143708"}@@即看影视[AS] AppSk@@{"host":"https://kankelm.cn:2024/appdomain.txt","key":"ygcnbcvybqqckwqy","iv":"1583560747143708"}@@看客联盟[AS] AppSk@@{"host":"https://dmsk.oss-rg-china-mainland.aliyuncs.com/dmapp/dmapi.txt","key":"ygcnbcobcegtgigg","iv":"4058263969143708"}@@2k动漫[AS] diff --git "a/json/App\346\250\241\346\235\277\351\205\215\347\275\256.json" "b/json/App\346\250\241\346\235\277\351\205\215\347\275\256.json" index 00d03223..acca5464 100644 --- "a/json/App\346\250\241\346\235\277\351\205\215\347\275\256.json" +++ "b/json/App\346\250\241\346\235\277\351\205\215\347\275\256.json" @@ -23,6 +23,198 @@ "password": "", "会员时长": "", "lazyheader": {} + }, + "仓鼠": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://ceshi307386.oss-cn-beijing.aliyuncs.com/ceshi421.txt", + "key": "da61247f5b662597", + "iv": "da61247f5b662597", + "verify": "true" + }, + "紫金": { + "muban": "AppGet", + "host": "", + "hosturl": "https://snysw.xyz/mf4kzs327.txt", + "key": "1234567887654321", + "iv": "1234567887654321", + "verify": "true" + }, + "云云": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://staraugust123456.oss-cn-hangzhou.aliyuncs.com/2.txt", + "key": "staraugust123456", + "iv": "staraugust123456", + "verify": "true" + }, + "奇奇": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://yun-1316442804.cos.ap-guangzhou.myqcloud.com/a.txt", + "key": "123456789abcdefg", + "iv": "123456789abcdefg", + "verify": "true" + }, + "鲸鱼": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://jingyu4k-1312635929.cos.ap-nanjing.myqcloud.com/1.json", + "key": "AAdgrdghjfgswerA", + "iv": "AAdgrdghjfgswerA", + "verify": "true" + }, + "咖啡": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://daen-1256234123.cos.ap-shanghai.myqcloud.com/MuQi/mqxh.txt", + "key": "37kj83zs1q16jk6t", + "iv": "37kj83zs1q16jk6t", + "verify": "true" + }, + "小猪": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://tiantangyoulu.oss-cn-beijing.aliyuncs.com/tengxunyun.txt", + "key": "seb5tq9mykp2w9ry", + "iv": "seb5tq9mykp2w9ry", + "verify": "true" + }, + "影视": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://aysappto.oss-cn-chengdu.aliyuncs.com/qj2.txt", + "key": "sada21321sdq231d", + "iv": "sada21321sdq231d", + "verify": "true" + }, + "数字": { + "muban": "AppGet", + "host": "http://app1-0-0.87333.cc", + "hosturl": "", + "key": "VwsHxkCViDXEExWa", + "iv": "VwsHxkCViDXEExWa", + "verify": "true" + }, + "火锅": { + "muban": "AppGet", + "host": "https://ios.hgyx.vip", + "hosturl": "", + "key": "062dec75d039980e", + "iv": "062dec75d039980e", + "verify": "true" + }, + "五八": { + "muban": "AppGet", + "host": "https://dy.58ys.vip", + "hosturl": "", + "key": "JEWibY1AgWF0V1xx", + "iv": "JEWibY1AgWF0V1xx", + "verify": "true" + }, + "旗星": { + "muban": "AppGet", + "host": "http://ys.qist.top", + "hosturl": "", + "key": "2SWSPFxugBLPPOKo", + "iv": "2SWSPFxugBLPPOKo", + "verify": "true" + }, + "灵虎": { + "muban": "AppGet", + "host": "", + "hosturl": "https://bind.315999.xyz/89.txt", + "key": "#getapp@TMD@2025", + "iv": "#getapp@TMD@2025", + "verify": "true" + }, + "剧梦": { + "muban": "AppGet", + "host": "https://www.jumengwu.com", + "hosturl": "", + "key": "1f0a873caf2550a5", + "iv": "1f0a873caf2550a5", + "verify": "true" + }, + "火狐": { + "muban": "AppGet", + "host": "http://huohu.yihn.cc", + "hosturl": "", + "key": "huohushipingetap", + "iv": "huohushipingetap", + "verify": "true" + }, + "金牌": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://dtqj.ggtvb.cc/dtjp.txt", + "key": "eecbio48dsq131ee", + "iv": "eecbio48dsq131ee", + "verify": "true" + }, + "爱盈": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://aysappto.oss-cn-chengdu.aliyuncs.com/qj3.txt", + "key": "sda1231sasddad21", + "iv": "sda1231sasddad21", + "verify": "true" + }, + "顾我": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://guwozj-1319364746.cos.ap-guangzhou.myqcloud.com/guwo.txt", + "key": "ca94b06ca3c7d80e", + "iv": "ca94b06ca3c7d80e", + "verify": "true" + }, + "爆炸": { + "muban": "AppQiji", + "host": "", + "hosturl": "https://daen-1256234123.cos.ap-shanghai.myqcloud.com/MuQi/mqxh.txt", + "key": "37kj83zs1q16jk6t", + "iv": "37kj83zs1q16jk6t", + "verify": "true" + }, + "橘子": { + "muban": "AppQiji", + "host": "https://juziapp.tpmbt.cn", + "hosturl": "", + "key": "K3h6YvSU8BTUfEcb", + "iv": "K3h6YvSU8BTUfEcb", + "verify": "true" + }, + "丫丫动漫": { + "muban": "AppGet", + "host": "http://tv.yy-fun.cc", + "hosturl": "", + "key": "qkxnwkfjwpcnwycl", + "iv": "qkxnwkfjwpcnwycl", + "verify": "true" + }, + "咕咕动漫": { + "muban": "AppGet", + "host": "https://www.gugu3.com", + "hosturl": "", + "key": "nKfZ8KX6JTNWRzTD", + "iv": "nKfZ8KX6JTNWRzTD", + "verify": "true" + }, + "元咲动漫": { + "muban": "AppGet", + "host": "http://cic.aicg.fun", + "hosturl": "", + "key": "2c4h36abd96se10u", + "iv": "2c4h36abd96se10u", + "verify": "true" + }, + "方舟动漫": { + "muban": "AppGet", + "host": "https://www.cyfz.vip", + "hosturl": "", + "key": "e72cdfd629e8895d", + "iv": "e72cdfd629e8895d", + "verify": "true" } }, "Appmuou": { @@ -40,14 +232,6 @@ "key1": "", "key2": "", "version": "" - }, - "光映视界": { - "host": "", - "hosturl": "https://ymdtsy.lingutv.cn/shark/api.txt", - "key": "IKXRx4M6cB45SNTs", - "key1": "rectangleadsadxa", - "key2": "aassddwwxxllsx1x", - "version": "2.2.0" } } } \ No newline at end of file From 4b7722f4adf411b405de64918e8fc3b4985e801d Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Thu, 15 Jan 2026 15:33:54 +0800 Subject: [PATCH 022/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=85=B7=E6=88=91?= =?UTF-8?q?=E9=9F=B3=E4=B9=90=E7=9B=B8=E5=85=B3=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\351\237\263\344\271\220[\345\220\254].js" | 12 ++++++-- ...\351\237\263\344\271\220[\345\220\254].js" | 29 ++++++++++++++----- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git "a/spider/js/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" "b/spider/js/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" index 766d76fe..1edc387c 100644 --- "a/spider/js/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" +++ "b/spider/js/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" @@ -33,8 +33,16 @@ var rule = { let data = JSON.parse(await request(url, { headers: rule.headers })); - let mp3 = data.data.mp3; - return {parse: 0, url: mp3, header: rule.headers}; + let songData = data.data; + return { + parse: 0, + url: songData.mp3, // 播放链接 + header: rule.headers, // 请求头 + lrc: songData.lrc, // 歌词内容 + img: songData.pic, // 封面图片 + title: songData.mname, // 歌名 + singer: songData.sname // 歌手 + }; }, 推荐: "*", 一级: '.mobile-list&&.mobile-list-item;.songname&&Text;.lazyload&&data-src;.authorname&&Text;a&&href', diff --git "a/spider/js_dr2/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" "b/spider/js_dr2/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" index 9d1baf95..80c3539f 100644 --- "a/spider/js_dr2/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" +++ "b/spider/js_dr2/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" @@ -21,20 +21,35 @@ var rule = { }, class_parse: '.aside-menu-list.channel&&[href*=list];a&&Text;a&&href;.(list.*).htm', play_parse: true, + + // --- 重构的核心部分 --- lazy: $js.toString(() => { + // 1. 将详情页 URL 替换为 API 接口 URL input = input.replace(/play\/(\w+)\.htm/, 'ajax/?act=songinfo&id=$1&lang='); - log(input); - let mp3 = JSON.parse(request(input)).data.mp3; - input = {parse: 0, url: mp3, header: rule.headers}; + + // 2. 发起请求并解析 JSON + let html = request(input); + let json = JSON.parse(html); + let data = json.data; + + // 3. 构造播放对象,包含歌词和元数据 + input = { + parse: 0, + url: data.mp3, // 播放链接 + header: rule.headers, // 请求头 + lrc: data.lrc, // 歌词内容 + img: data.pic, // 封面图片 + title: data.mname, // 歌名 + singer: data.sname // 歌手 + }; }), + // --------------------- + limit: 6, - // 图片来源:'@Referer=https://www.zz123.com/', 推荐: "*", 一级: '.mobile-list&&.mobile-list-item;.songname&&Text;.lazyload&&data-src;.authorname&&Text;a&&href', 二级: '*', - // searchUrl:'/search/?key=**&page=fypage', - // 搜索:'*', searchUrl: '/ajax/?act=search&key=**&lang=', - detailUrl: '/play/fyid.html', + detailUrl: '/play/fyid.html', // 修正:原来是 play/fyid.html,这里保持一致,lazy中正则会匹配 搜索: 'json:data;mname;pic;sname;id', } \ No newline at end of file From c105d0fec92eedb951a939a3d9a55f32d19f1761 Mon Sep 17 00:00:00 2001 From: Taois Date: Thu, 15 Jan 2026 19:42:19 +0800 Subject: [PATCH 023/101] =?UTF-8?q?feat:=20=E5=90=88=E5=B9=B6=E7=A7=8B?= =?UTF-8?q?=E7=A7=8B=E6=8F=90=E4=BE=9B=E7=9A=84=E6=89=AB=E7=A0=81=E5=85=A5?= =?UTF-8?q?=E5=BA=93=E7=95=8C=E9=9D=A2=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cookie-butler/index.html | 63 ++++++++++++++++--- apps/cookie-butler/static/js/cookie.js | 2 +- apps/cookie-butler/static/js/jsencrypt.min.js | 1 + 3 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 apps/cookie-butler/static/js/jsencrypt.min.js diff --git a/apps/cookie-butler/index.html b/apps/cookie-butler/index.html index 51942ecc..ca9d936d 100644 --- a/apps/cookie-butler/index.html +++ b/apps/cookie-butler/index.html @@ -12,6 +12,7 @@ +
    @@ -19,10 +20,13 @@ @@ -93,28 +97,67 @@ const textValue = document.getElementById("cookie-res").value || ''; const active_name = activeLi.textContent.trim(); const active_key = activeLi.getAttribute('data-platform').trim(); - const save_key = active_key === 'ali' ? active_key + '_token' : active_key + '_cookie'; + let save_key = '' + if (/ali|pikpak/.test(active_key)) { + save_key = active_key + '_token' + } else { + save_key = active_key + '_cookie'; + } + console.log(`准备入库cookie:${active_name} ${save_key},值为:${textValue}`); const cookie_auth_code = prompt('cookie入库功能需要管理员授权码,请你正确输入后继续'); if (cookie_auth_code) { - // 使用 axios 发送 POST 请求 - axios.post('/admin/cookie-set', { - cookie_auth_code: cookie_auth_code, - key: save_key, - value: textValue.trim().replaceAll('\n', '') - }) - .then(response => { + if (save_key.includes('pikpak')) { + // 使用 axios 发送 POST 请求 + axios.post('/admin/cookie-set', { + cookie_auth_code: cookie_auth_code, + key: save_key, + value: textValue.split(';')[0].trim().replaceAll('\n', '') + }).then(response => { if (response.data.success) { alert(`Cookie 入库成功:${active_name} (${save_key})`); } else { alert(`入库失败:${response.data.message}`); } - }) - .catch(error => { + }).catch(error => { + console.error('请求失败:', error); + alert(`入库失败,服务器出现问题,请稍后再试。\n${error.response.data.message}`); + }); + axios.post('/admin/cookie-set', { + cookie_auth_code: cookie_auth_code, + key: save_key.replace('token', 'refresh_token'), + value: textValue.split(';')[1].trim().replaceAll('\n', '') + }).then(response => { + if (response.data.success) { + alert(`Cookie 入库成功:${active_name} (${save_key.replace('token', 'refresh_token')})`); + } else { + alert(`入库失败:${response.data.message}`); + } + }).catch(error => { console.error('请求失败:', error); alert(`入库失败,服务器出现问题,请稍后再试。\n${error.response.data.message}`); }); + } else { + // 使用 axios 发送 POST 请求 + axios.post('/admin/cookie-set', { + cookie_auth_code: cookie_auth_code, + key: save_key, + value: textValue.trim().replaceAll('\n', '') + }) + .then(response => { + if (response.data.success) { + alert(`Cookie 入库成功:${active_name} (${save_key})`); + } else { + alert(`入库失败:${response.data.message}`); + } + }) + .catch(error => { + console.error('请求失败:', error); + alert(`入库失败,服务器出现问题,请稍后再试。\n${error.response.data.message}`); + }); + } + } } else { alert('至少选中一个cookie入库项目'); diff --git a/apps/cookie-butler/static/js/cookie.js b/apps/cookie-butler/static/js/cookie.js index bff8f94a..f01be452 100644 --- a/apps/cookie-butler/static/js/cookie.js +++ b/apps/cookie-butler/static/js/cookie.js @@ -20,7 +20,7 @@ function showToast(message, type = 'success') { // 初始化页面 async function initializePage() { // 加载cookie - const platforms = ['ali', 'quark', 'uc', 'uc_token', 'bili', 'baidu']; + const platforms = ['ali', 'quark', 'quark_token', 'uc', 'uc_token', 'bili', 'yun', 'baidu', 'pikpak']; // 绑定按钮事件 platforms.forEach(platform => { diff --git a/apps/cookie-butler/static/js/jsencrypt.min.js b/apps/cookie-butler/static/js/jsencrypt.min.js new file mode 100644 index 00000000..27c29d5e --- /dev/null +++ b/apps/cookie-butler/static/js/jsencrypt.min.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.JSEncrypt={})}(this,function(t){"use strict";var e="0123456789abcdefghijklmnopqrstuvwxyz";function a(t){return e.charAt(t)}function i(t,e){return t&e}function u(t,e){return t|e}function r(t,e){return t^e}function n(t,e){return t&~e}function s(t){if(0==t)return-1;var e=0;return 0==(65535&t)&&(t>>=16,e+=16),0==(255&t)&&(t>>=8,e+=8),0==(15&t)&&(t>>=4,e+=4),0==(3&t)&&(t>>=2,e+=2),0==(1&t)&&++e,e}function o(t){for(var e=0;0!=t;)t&=t-1,++e;return e}var h="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function c(t){var e,i,r="";for(e=0;e+3<=t.length;e+=3)i=parseInt(t.substring(e,e+3),16),r+=h.charAt(i>>6)+h.charAt(63&i);for(e+1==t.length?(i=parseInt(t.substring(e,e+1),16),r+=h.charAt(i<<2)):e+2==t.length&&(i=parseInt(t.substring(e,e+2),16),r+=h.charAt(i>>2)+h.charAt((3&i)<<4));0<(3&r.length);)r+="=";return r}function f(t){var e,i="",r=0,n=0;for(e=0;e>2),n=3&s,r=1):1==r?(i+=a(n<<2|s>>4),n=15&s,r=2):2==r?(i+=a(n),i+=a(s>>2),n=3&s,r=3):(i+=a(n<<2|s>>4),i+=a(15&s),r=0))}return 1==r&&(i+=a(n<<2)),i}var l,p=function(t,e){return(p=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i])})(t,e)};var g,d=function(t){var e;if(void 0===l){var i="0123456789ABCDEF",r=" \f\n\r\t \u2028\u2029";for(l={},e=0;e<16;++e)l[i.charAt(e)]=e;for(i=i.toLowerCase(),e=10;e<16;++e)l[i.charAt(e)]=e;for(e=0;e>16,r[r.length]=n>>8&255,r[r.length]=255&n,s=n=0):n<<=6}}switch(s){case 1:throw new Error("Base64 encoding incomplete: at least 2 bits missing");case 2:r[r.length]=n>>10;break;case 3:r[r.length]=n>>16,r[r.length]=n>>8&255}return r},re:/-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/,unarmor:function(t){var e=v.re.exec(t);if(e)if(e[1])t=e[1];else{if(!e[2])throw new Error("RegExp out of sync");t=e[2]}return v.decode(t)}},m=1e13,y=function(){function t(t){this.buf=[+t||0]}return t.prototype.mulAdd=function(t,e){var i,r,n=this.buf,s=n.length;for(i=0;ie&&(t=t.substring(0,e)+b),t}var w,D=function(){function i(t,e){this.hexDigits="0123456789ABCDEF",t instanceof i?(this.enc=t.enc,this.pos=t.pos):(this.enc=t,this.pos=e)}return i.prototype.get=function(t){if(void 0===t&&(t=this.pos++),t>=this.enc.length)throw new Error("Requesting byte offset "+t+" on a stream of length "+this.enc.length);return"string"==typeof this.enc?this.enc.charCodeAt(t):this.enc[t]},i.prototype.hexByte=function(t){return this.hexDigits.charAt(t>>4&15)+this.hexDigits.charAt(15&t)},i.prototype.hexDump=function(t,e,i){for(var r="",n=t;n>u&1?"1":"0";if(s.length>i)return n+E(s,i)}return n+s},i.prototype.parseOctetString=function(t,e,i){if(this.isASCII(t,e))return E(this.parseStringISO(t,e),i);var r=e-t,n="("+r+" byte)\n";(i/=2)i)return E(r,i);n=new y,s=0}}return 0>6,this.tagConstructed=0!=(32&e),this.tagNumber=31&e,31==this.tagNumber){for(var i=new y;e=t.get(),i.mulAdd(128,127&e),128&e;);this.tagNumber=i.simplify()}}return t.prototype.isUniversal=function(){return 0===this.tagClass},t.prototype.isEOC=function(){return 0===this.tagClass&&0===this.tagNumber},t}(),B=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],A=(1<<26)/B[B.length-1],O=function(){function b(t,e,i){null!=t&&("number"==typeof t?this.fromNumber(t,e,i):null==e&&"string"!=typeof t?this.fromString(t,256):this.fromString(t,e))}return b.prototype.toString=function(t){if(this.s<0)return"-"+this.negate().toString(t);var e;if(16==t)e=4;else if(8==t)e=3;else if(2==t)e=1;else if(32==t)e=5;else{if(4!=t)return this.toRadix(t);e=2}var i,r=(1<>h)&&(n=!0,s=a(i));0<=o;)h>(h+=this.DB-e)):(i=this[o]>>(h-=e)&r,h<=0&&(h+=this.DB,--o)),0>24},b.prototype.shortValue=function(){return 0==this.t?this.s:this[0]<<16>>16},b.prototype.signum=function(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1},b.prototype.toByteArray=function(){var t=this.t,e=[];e[0]=this.s;var i,r=this.DB-t*this.DB%8,n=0;if(0>r)!=(this.s&this.DM)>>r&&(e[n++]=i|this.s<>(r+=this.DB-8)):(i=this[t]>>(r-=8)&255,r<=0&&(r+=this.DB,--t)),0!=(128&i)&&(i|=-256),0==n&&(128&this.s)!=(128&i)&&++n,(0=this.t?0!=this.s:0!=(this[e]&1<>n-a&u:(f=(t[p]&(1<>this.DB+n-a)),h=i;0==(1&f);)f>>=1,--h;if((n-=h)<0&&(n+=this.DB,--p),g)o[f].copyTo(s),g=!1;else{for(;1this.DB?(this[this.t-1]|=(o&(1<>this.DB-s):this[this.t-1]|=o<=this.DB&&(s-=this.DB))}8==i&&0!=(128&+t[0])&&(this.s=-1,0>r|o,o=(this[h]&n)<=this.t)e.t=0;else{var r=t%this.DB,n=this.DB-r,s=(1<>r;for(var o=i+1;o>r;0>=this.DB;if(t.t>=this.DB;r+=this.s}else{for(r+=this.s;i>=this.DB;r-=t.s}e.s=r<0?-1:0,r<-1?e[i++]=this.DV+r:0=e.DV&&(t[i+e.t]-=e.DV,t[i+e.t+1]=1)}0>this.F2:0),l=this.FV/f,p=(1<=i&&(this.dMultiply(r),this.dAddOffset(o,0),o=s=0))}0t&&this.subTo(b.ONE.shiftLeft(t-1),this);else{var r=[],n=7&t;r.length=1+(t>>3),e.nextBytes(r),0>=this.DB;if(t.t>=this.DB;r+=this.s}else{for(r+=this.s;i>=this.DB;r+=t.s}e.s=r<0?-1:0,0=this.DV;)this[e]-=this.DV,++e>=this.t&&(this[this.t++]=0),++this[e]}},b.prototype.multiplyLowerTo=function(t,e,i){var r=Math.min(this.t+t.t,e);for(i.s=0,i.t=r;0>1)&&(t=B.length);for(var n=M(),s=0;st&&n.subTo(b.ONE.shiftLeft(t-1),n),n.isProbablePrime(e)?setTimeout(function(){r()},0):setTimeout(s,0)};setTimeout(s,0)}else{var o=[],h=7&t;o.length=1+(t>>3),e.nextBytes(o),0>15,this.um=(1<>15)*this.mpl&this.um)<<15)&t.DM;for(t[i=e+this.m.t]+=this.m.am(0,r,t,e,0,this.m.t);t[i]>=t.DV;)t[i]-=t.DV,t[++i]++}t.clamp(),t.drShiftTo(this.m.t,t),0<=t.compareTo(this.m)&&t.subTo(this.m,t)},t.prototype.mulTo=function(t,e,i){t.multiplyTo(e,i),this.reduce(i)},t.prototype.sqrTo=function(t,e){t.squareTo(e),this.reduce(e)},t}(),P=function(){function t(t){this.m=t,this.r2=M(),this.q3=M(),O.ONE.dlShiftTo(2*t.t,this.r2),this.mu=this.r2.divide(t)}return t.prototype.convert=function(t){if(t.s<0||t.t>2*this.m.t)return t.mod(this.m);if(t.compareTo(this.m)<0)return t;var e=M();return t.copyTo(e),this.reduce(e),e},t.prototype.revert=function(t){return t},t.prototype.reduce=function(t){for(t.drShiftTo(this.m.t-1,this.r2),t.t>this.m.t+1&&(t.t=this.m.t+1,t.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);t.compareTo(this.r2)<0;)t.dAddOffset(1,this.m.t+1);for(t.subTo(this.r2,t);0<=t.compareTo(this.m);)t.subTo(this.m,t)},t.prototype.mulTo=function(t,e,i){t.multiplyTo(e,i),this.reduce(i)},t.prototype.sqrTo=function(t,e){t.squareTo(e),this.reduce(e)},t}();function M(){return new O(null)}function q(t,e){return new O(t,e)}"Microsoft Internet Explorer"==navigator.appName?(O.prototype.am=function(t,e,i,r,n,s){for(var o=32767&e,h=e>>15;0<=--s;){var a=32767&this[t],u=this[t++]>>15,c=h*a+u*o;n=((a=o*a+((32767&c)<<15)+i[r]+(1073741823&n))>>>30)+(c>>>15)+h*u+(n>>>30),i[r++]=1073741823&a}return n},w=30):"Netscape"!=navigator.appName?(O.prototype.am=function(t,e,i,r,n,s){for(;0<=--s;){var o=e*this[t++]+i[r]+n;n=Math.floor(o/67108864),i[r++]=67108863&o}return n},w=26):(O.prototype.am=function(t,e,i,r,n,s){for(var o=16383&e,h=e>>14;0<=--s;){var a=16383&this[t],u=this[t++]>>14,c=h*a+u*o;n=((a=o*a+((16383&c)<<14)+i[r]+n)>>28)+(c>>14)+h*u,i[r++]=268435455&a}return n},w=28),O.prototype.DB=w,O.prototype.DM=(1<>>16)&&(t=e,i+=16),0!=(e=t>>8)&&(t=e,i+=8),0!=(e=t>>4)&&(t=e,i+=4),0!=(e=t>>2)&&(t=e,i+=2),0!=(e=t>>1)&&(t=e,i+=1),i}O.ZERO=F(0),O.ONE=F(1);var K=function(){function t(){this.i=0,this.j=0,this.S=[]}return t.prototype.init=function(t){var e,i,r;for(e=0;e<256;++e)this.S[e]=e;for(e=i=0;e<256;++e)i=i+this.S[e]+t[e%t.length]&255,r=this.S[e],this.S[e]=this.S[i],this.S[i]=r;this.i=0,this.j=0},t.prototype.next=function(){var t;return this.i=this.i+1&255,this.j=this.j+this.S[this.i]&255,t=this.S[this.i],this.S[this.i]=this.S[this.j],this.S[this.j]=t,this.S[t+this.S[this.i]&255]},t}();var k,_,z=256,Z=null;if(null==Z){Z=[];var G=void(_=0);if(window.crypto&&window.crypto.getRandomValues){var $=new Uint32Array(256);for(window.crypto.getRandomValues($),G=0;G<$.length;++G)Z[_++]=255&$[G]}var Y=function(t){if(this.count=this.count||0,256<=this.count||z<=_)window.removeEventListener?window.removeEventListener("mousemove",Y,!1):window.detachEvent&&window.detachEvent("onmousemove",Y);else try{var e=t.x+t.y;Z[_++]=255&e,this.count+=1}catch(t){}};window.addEventListener?window.addEventListener("mousemove",Y,!1):window.attachEvent&&window.attachEvent("onmousemove",Y)}function J(){if(null==k){for(k=new K;_>6|192):(i[--e]=63&n|128,i[--e]=n>>6&63|128,i[--e]=n>>12|224)}i[--e]=0;for(var s=new X,o=[];2>3);if(null==e)return null;var i=this.doPublic(e);if(null==i)return null;var r=i.toString(16);return 0==(1&r.length)?r:"0"+r},t.prototype.setPrivate=function(t,e,i){null!=t&&null!=e&&0>1;this.e=parseInt(e,16);for(var n=new O(e,16);;){for(;this.p=new O(t-r,1,i),0!=this.p.subtract(O.ONE).gcd(n).compareTo(O.ONE)||!this.p.isProbablePrime(10););for(;this.q=new O(r,1,i),0!=this.q.subtract(O.ONE).gcd(n).compareTo(O.ONE)||!this.q.isProbablePrime(10););if(this.p.compareTo(this.q)<=0){var s=this.p;this.p=this.q,this.q=s}var o=this.p.subtract(O.ONE),h=this.q.subtract(O.ONE),a=o.multiply(h);if(0==a.gcd(n).compareTo(O.ONE)){this.n=this.p.multiply(this.q),this.d=n.modInverse(a),this.dmp1=this.d.mod(o),this.dmq1=this.d.mod(h),this.coeff=this.q.modInverse(this.p);break}}},t.prototype.decrypt=function(t){var e=q(t,16),i=this.doPrivate(e);return null==i?null:function(t,e){var i=t.toByteArray(),r=0;for(;r=i.length)return null;var n="";for(;++r>3)},t.prototype.generateAsync=function(t,e,n){var s=new X,o=t>>1;this.e=parseInt(e,16);var h=new O(e,16),a=this,u=function(){var e=function(){if(a.p.compareTo(a.q)<=0){var t=a.p;a.p=a.q,a.q=t}var e=a.p.subtract(O.ONE),i=a.q.subtract(O.ONE),r=e.multiply(i);0==r.gcd(h).compareTo(O.ONE)?(a.n=a.p.multiply(a.q),a.d=h.modInverse(r),a.dmp1=a.d.mod(e),a.dmq1=a.d.mod(i),a.coeff=a.q.modInverse(a.p),setTimeout(function(){n()},0)):setTimeout(u,0)},i=function(){a.q=M(),a.q.fromNumberAsync(o,1,s,function(){a.q.subtract(O.ONE).gcda(h,function(t){0==t.compareTo(O.ONE)&&a.q.isProbablePrime(10)?setTimeout(e,0):setTimeout(i,0)})})},r=function(){a.p=M(),a.p.fromNumberAsync(t-o,1,s,function(){a.p.subtract(O.ONE).gcda(h,function(t){0==t.compareTo(O.ONE)&&a.p.isProbablePrime(10)?setTimeout(i,0):setTimeout(r,0)})})};setTimeout(r,0)};setTimeout(u,0)},t.prototype.sign=function(t,e,i){var r=function(t,e){if(e=e?t:new Array(e-t.length+1).join("0")+t},this.getString=function(){return this.s},this.setString=function(t){this.hTLV=null,this.isModified=!0,this.s=t,this.hV=stohex(t)},this.setByDateValue=function(t,e,i,r,n,s){var o=new Date(Date.UTC(t,e-1,i,r,n,s,0));this.setByDate(o)},this.getFreshValueHex=function(){return this.hV}},tt.lang.extend(et.asn1.DERAbstractTime,et.asn1.ASN1Object),et.asn1.DERAbstractStructured=function(t){et.asn1.DERAbstractString.superclass.constructor.call(this),this.setByASN1ObjectArray=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array=t},this.appendASN1Object=function(t){this.hTLV=null,this.isModified=!0,this.asn1Array.push(t)},this.asn1Array=new Array,void 0!==t&&void 0!==t.array&&(this.asn1Array=t.array)},tt.lang.extend(et.asn1.DERAbstractStructured,et.asn1.ASN1Object),et.asn1.DERBoolean=function(){et.asn1.DERBoolean.superclass.constructor.call(this),this.hT="01",this.hTLV="0101ff"},tt.lang.extend(et.asn1.DERBoolean,et.asn1.ASN1Object),et.asn1.DERInteger=function(t){et.asn1.DERInteger.superclass.constructor.call(this),this.hT="02",this.setByBigInteger=function(t){this.hTLV=null,this.isModified=!0,this.hV=et.asn1.ASN1Util.bigIntToMinTwosComplementsHex(t)},this.setByInteger=function(t){var e=new O(String(t),10);this.setByBigInteger(e)},this.setValueHex=function(t){this.hV=t},this.getFreshValueHex=function(){return this.hV},void 0!==t&&(void 0!==t.bigint?this.setByBigInteger(t.bigint):void 0!==t.int?this.setByInteger(t.int):"number"==typeof t?this.setByInteger(t):void 0!==t.hex&&this.setValueHex(t.hex))},tt.lang.extend(et.asn1.DERInteger,et.asn1.ASN1Object),et.asn1.DERBitString=function(t){if(void 0!==t&&void 0!==t.obj){var e=et.asn1.ASN1Util.newObject(t.obj);t.hex="00"+e.getEncodedHex()}et.asn1.DERBitString.superclass.constructor.call(this),this.hT="03",this.setHexValueIncludingUnusedBits=function(t){this.hTLV=null,this.isModified=!0,this.hV=t},this.setUnusedBitsAndHexValue=function(t,e){if(t<0||7 Date: Thu, 15 Jan 2026 23:42:48 +0800 Subject: [PATCH 024/101] =?UTF-8?q?add:=20=E6=96=B0=E5=A2=9E=E7=95=AA?= =?UTF-8?q?=E8=8C=84=E6=BC=AB=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\345\260\217\350\257\264[\344\271\246].js" | 2 +- ...\346\274\253\347\224\273[\347\224\273].js" | 112 ++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 "spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" diff --git "a/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" "b/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" index b659fa25..53cd0233 100644 --- "a/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" +++ "b/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" @@ -31,7 +31,7 @@ var rule = { homeUrl: 'https://fanqienovel.com/api/author/book/category_list/v0/', url: '/api/author/library/book_list/v0/?page_count=18&page_index=(fypage-1)&gender=1&category_id=fyclass&creation_status=-1&word_count=-1&book_type=-1&sort=0#fyfilter', // searchUrl: fqweb_host + '/search?query=**&page=fypage', - searchUrl: fqweb_host + '/api/search?key=**&tab_type=3&offset=0&page=fypage', + searchUrl: fqweb_host + '/api/search?key=**&tab_type=3&offset=((fypage-1)*10)', searchable: 2, quickSearch: 0, filterable: 1, diff --git "a/spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" "b/spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" new file mode 100644 index 00000000..230432e8 --- /dev/null +++ "b/spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" @@ -0,0 +1,112 @@ +/* +@header({ + searchable: 1, + filterable: 0, + quickSearch: 0, + title: '番茄漫画', + '类型': '漫画', + lang: 'ds' +}) +*/ + +var rule = { + 类型: '漫画', + title: '番茄漫画', + host: 'https://qkfqapi.vv9v.cn', + url: '', + searchUrl: '/api/search?key=**&tab_type=8&offset=((fypage-1)*10)', + detailUrl: '/api/detail?book_id=fyid', + headers: {'User-Agent': 'UC_UA'}, + searchable: 1, + quickSearch: 0, + filterable: 0, + double: true, + play_parse: true, + limit: 12, + // class_parse: async function () { + // let {input, pdfa, pdfh, pd} = this; + // return {} + // }, + lazy: async function () { + let {input, pdfa, pdfh} = this; + let title = input.split('@')[1]; + input = input.split('@')[0]; + let content_url = `https://qkfqapi.vv9v.cn/api/content?tab=漫画&item_id=${input}&show_html=0`; // 正文获取接口 + let jsonStr = await request(content_url); + let images = jsonStr.parseX.data.images; + images = pdfa(images, 'img'); + let pics = [] + for (let img of images) { + let pic = pdfh(img, 'img&&src'); + pics.push(pic); + } + return {parse: 0, url: 'pics://' + pics.join('&&')} + }, + 推荐: async function () { + return [{ + vod_id: 'only_search', + vod_name: '纯搜索源哦!', + vod_tag: 'action', + vod_pic: this.publicUrl + '/images/icon_cookie/搜索.jpg' + }]; + }, + 一级: async function () { + return []; + }, + 二级: async function () { + let {input, orId} = this; + // log('input', input); + // log('orId', orId); + let html = await request(input); + let json = JSON.parse(html); + let data = json.data.data; + let VOD = {}; + VOD.vod_name = data.book_name; + VOD.type_name = data.category; + VOD.vod_pic = data.thumb_url; + VOD.vod_content = data.abstract; + VOD.vod_remarks = data.sub_info; + VOD.vod_year = ''; + VOD.vod_area = ''; + VOD.vod_actor = ''; + VOD.vod_director = data.author; + VOD.vod_play_from = '番茄漫画'; + let jsonStr = await request(`https://qkfqapi.vv9v.cn/api/book?book_id=${orId}`); + let book_info = jsonStr.parseX.data.data; + let list = book_info.chapterListWithVolume.flat(); + let urls = []; + list.forEach((it, index) => { + urls.push(it.title + '$' + it.itemId + '@' + it.title); + }); + VOD.vod_play_url = urls.join('#'); + return VOD + }, + 搜索: async function () { + let {input, MY_PAGE} = this; + // if (Number(MY_PAGE) > 1) { + // return [] + // } + print(input) + let html = await request(input); + let json = JSON.parse(html); + let data = json.data.search_tabs[3].data; + let d = []; + for (let it of data.filter(i => i.book_data)) { + let book = it.book_data[0]; + // console.log(book) + d.push({ + title: book.book_name, + url: book.book_id, + desc: book.author, + content: book.book_abstract || book.abstract, + pic_url: book.thumb_url + }); + } + return setResult(d) + }, + action: async function (action, value) { + if (action === 'only_search') { + return '此源为纯搜索源,你直接全局搜索这个源或者使用此页面的源内搜索就好了' + } + } +} \ No newline at end of file From b395b4dbce81762afbcb17730b79f0f9440cdcfb Mon Sep 17 00:00:00 2001 From: Taois Date: Thu, 15 Jan 2026 23:59:49 +0800 Subject: [PATCH 025/101] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E5=87=A0?= =?UTF-8?q?=E4=B8=AA=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...252\350\214\204\345\260\217\350\257\264[\344\271\246].js" | 5 +++++ 1 file changed, 5 insertions(+) diff --git "a/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" "b/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" index 53cd0233..12279717 100644 --- "a/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" +++ "b/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" @@ -22,6 +22,11 @@ const {requestHtml} = $.require('./_lib.request.js'); // const fqweb_host = 'http://fqweb.jsj66.com'; // const fqweb_host = 'http://fanqie.mduge.com'; const fqweb_host = 'https://qkfqapi.vv9v.cn'; +// const fqweb_host = 'http://101.35.133.34:5000/docs'; //备选 +// const fqweb_host = 'http://103.236.91.147:9999/docs'; //备选 +// const fqweb_host = 'http://47.108.80.161:5005/docs'; //备选 +// const fqweb_host = 'http://140.143.165.56:9999/docs'; //备选 +// const fqweb_host = 'http://8.148.83.169:22222/docs'; //备选 var rule = { 类型: '小说', From dd58dbd14b89e0a333943535c5261a5301ee97fe Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Fri, 16 Jan 2026 00:11:34 +0800 Subject: [PATCH 026/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/map.txt | 4 - ...\346\235\277\351\205\215\347\275\256.json" | 8 - public/sub/order_common.example.html | 4 +- ...\350\257\273\344\271\246[\344\271\246].js" | 155 +++++++++++++++++ ...\345\212\251\346\211\213[\344\271\246].js" | 160 ++++++++++++++++++ 5 files changed, 318 insertions(+), 13 deletions(-) create mode 100644 "spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" create mode 100644 "spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" diff --git a/config/map.txt b/config/map.txt index a6603726..13760290 100644 --- a/config/map.txt +++ b/config/map.txt @@ -38,7 +38,6 @@ AppFei@@https://ysa.yy-fun.cc/feiapp@@森林动漫[AF] AppGet@@{"host":"https://snysw.xyz/mf4kzs327.txt","key":"1234567887654321"}@@魔方[AG¹] AppGet@@{"host":"https://gitee.com/wmmoliill/wimg/raw/master/img/bk/9.txt","key":"88689667dce61725"}@@茉莉[AG¹] AppGet@@{"host":"http://ys.qist.top","key":"2SWSPFxugBLPPOKo"}@@旗星[AG¹] -AppGet@@{"host":"https://api1.bffree.cn","key":"2015692015692015"}@@橘子[AG¹] AppGet@@{"host":"https://dy.58ys.vip","key":"JEWibY1AgWF0V1xx"}@@五八[AG¹] AppGet@@{"host":"https://mac.555618.xyz","key":"#getapp@TMD@2025"}@@玲珑[AG¹] AppGet@@{"host":"https://app.omofun1.top","key":"66dc309cbeeca454"}@@OMOfun[AG¹] @@ -50,16 +49,13 @@ AppSk@@{"host":"https://sk.xiaoyaoys.top/skkkkkkk.txt","key":"ygcnbcczduwydmrs", AppV6@@{"api":"http://yjyi.juyongjiu.com/icciu_api.php/v1.vod","datasignkey":"6QQNUsP3PkD2ajJCPCY8","apisignkey":"lvdoutv-1.0.0"}@@剧永久[AV⁶] AppV6@@http://jxfmax.juxiafan.com/icciu_api.php/v1.vod@@剧下饭[AV⁶] AppToV5@@http://118.89.203.120:8762@@番喜[ATV⁵] -AppToV5@@http://111.173.114.61:8762@@爱看剧Fax[ATV⁵] AppToV5@@http://38.55.237.41:8762@@皮皮虾[ATV⁵] -AppV2²@@https://www.heli888.cc@@河狸![AV²] AppV2²@@http://38.47.213.61:41271@@闪影[AV²] AppV2²@@http://v.lnhaozhenjin.cn@@好震惊[AV²] AppV2²@@http://jxfmax.juxiafan.com@@剧下饭[AV²] AppV1@@http://ziyuncms.feifan12.xyz/api.php@@紫云[AV¹] getapp3.4.4@@{"host":"https://staraugust123456.oss-cn-hangzhou.aliyuncs.com/2.txt","datakey":"staraugust123456","api":2}@@云云[AG³] getapp3.4.4@@{"host":"https://jingyu4k-1312635929.cos.ap-nanjing.myqcloud.com/1.json","datakey":"AAdgrdghjfgswerA","api":2}@@鲸鱼影视[AG³] -getapp3.4.4@@{"host":"https://www.guahd.com/1.txt","key":"f2A7D4B9E8C16531"}@@瓜萌[AG³] getapp3.4.4@@{"host":"https://99.jl8.top/1.txt","key":"xnybssspqtwotuwj"}@@七月[AG³] getapp3.4.4@@{"host":"http://tvb.yy-fun.cc","key":"jcTz6Jda2aKrH8Tk"}@@掌上追剧[AG³] AppHs@@{"host":"https://dy.jmzp.net.cn","app_id":"shiguang","deviceid":"","versionCode":"10000","UMENG_CHANNEL":"guan"}@@拾光视频[Hs] diff --git "a/json/App\346\250\241\346\235\277\351\205\215\347\275\256.json" "b/json/App\346\250\241\346\235\277\351\205\215\347\275\256.json" index acca5464..c78b8a10 100644 --- "a/json/App\346\250\241\346\235\277\351\205\215\347\275\256.json" +++ "b/json/App\346\250\241\346\235\277\351\205\215\347\275\256.json" @@ -176,14 +176,6 @@ "iv": "37kj83zs1q16jk6t", "verify": "true" }, - "橘子": { - "muban": "AppQiji", - "host": "https://juziapp.tpmbt.cn", - "hosturl": "", - "key": "K3h6YvSU8BTUfEcb", - "iv": "K3h6YvSU8BTUfEcb", - "verify": "true" - }, "丫丫动漫": { "muban": "AppGet", "host": "http://tv.yy-fun.cc", diff --git a/public/sub/order_common.example.html b/public/sub/order_common.example.html index 33cf163c..a82a7930 100644 --- a/public/sub/order_common.example.html +++ b/public/sub/order_common.example.html @@ -1,16 +1,18 @@ 设置中心 番茄小说 -大象影视 腾云驾雾 央视大全 IPTV [优] [盘] [漫] +[短] [官] [听] +[书] [搜] DS cat +DR2 hipy 推送 diff --git "a/spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" "b/spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" new file mode 100644 index 00000000..86b8b485 --- /dev/null +++ "b/spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" @@ -0,0 +1,155 @@ +/* +@header({ + searchable: 1, + filterable: 0, + quickSearch: 1, + title: '去读书[书]', + author: 'EylinSir', + '类型': '小说', + logo: 'http://www.qudushu.com/favicon.ico', + lang: 'ds' +}) +*/ + +var rule = { + 类型: '小说', + author: 'EylinSir', + title: '去读书[书]', + host: 'http://www.qudushu.com', + url: '/book/fyclass/0/fypage.html', + logo: 'http://www.qudushu.com/favicon.ico', + class_name: '玄幻魔法&武侠修真&都市言情&历史军事&穿越架空&游戏竞技', + class_url: 'sort1&sort2&sort3&sort4&sort5&sort6', + searchUrl: '/modules/article/search.php?q=**', + searchable: 1, + quickSearch: 1, + filterable: 0, + timeout: 10000, + play_parse: true, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36' + }, + request: async function (url, obj) { + obj = obj || {}; + try { + const response = await _fetch(url, { + method: obj.method || 'GET', + headers: obj.headers || this.headers + }); + return response.text(); + } catch (err) { + return ''; + } + }, + + 一级: async function () { + let {input, pdfa, pdfh, pd} = this; + let url = input.startsWith('http') ? input : this.host + '/book/' + input + '/0/1.html'; + let html = await this.request(url); + let d = []; + let items = pdfa(html, '.blockcontent .c_row') || pdfa(html, '.c_row') || []; + for (let item of items) { + let title = pdfh(item, '.c_subject a:eq(1)&&Text'); + let itemUrl = pd(item, '.c_subject a:eq(1)&&href'); + if (!title || !itemUrl) continue; + let remarks = pdfh(item, '.c_tag span:eq(1)&&Text') || ''; + let pic = pd(item, 'img&&src') || ''; + let content = pdfh(item, '.c_description&&Text') || ''; + d.push({ + title: title, + url: itemUrl, + desc: remarks, + pic_url: pic, + content: content, + }); + } + return setResult(d); + }, + + 二级: async function () { + let {input, pdfa, pdfh, pd} = this; + let html = await this.request(input); + let VOD = {}; + VOD.vod_name = pdfh(html, '[property="og:novel:book_name"]&&content') || ''; + VOD.type_name = ''; + VOD.vod_pic = pd(html, '.divbox.cf img&&src') || ''; + VOD.vod_content = pdfh(html, '.tabcontent .tabvalue:eq(0)&&Text') || ''; + VOD.vod_remarks = pdfh(html, 'h3 a&&Text') || ''; + VOD.vod_year = ''; + VOD.vod_area = ''; + VOD.vod_actor = pdfh(html, '[property="og:novel:author"]&&content') || ''; + VOD.vod_director = VOD.vod_actor; + VOD.vod_play_from = '去读书网'; + let toc_url = pd(html, 'a:contains(点击阅读)&&href') || ''; + if (toc_url && !toc_url.startsWith('http')) { + toc_url = this.host + toc_url; + } + let toc_html = toc_url ? await this.request(toc_url) : ''; + let chapters = []; + let chapterItems = pdfa(toc_html, '.index li') || []; + for (let chapter of chapterItems) { + let title = pdfh(chapter, 'a&&Text'); + let chapter_url = pd(chapter, 'a&&href'); + if (!title || !chapter_url) continue; + if (!chapter_url.startsWith('http')) { + chapter_url = this.host + chapter_url; + } + chapters.push(title + '$' + chapter_url); + } + VOD.vod_play_url = chapters.join('#'); + return VOD; + }, + + 搜索: async function () { + let {KEY, pdfa, pdfh, pd} = this; + let url = this.host + this.searchUrl.replace('**', encodeURIComponent(KEY)); + let html = await this.request(url); + if (!html) { + url = this.host + '/modules/article/search.php?q=' + encodeURIComponent(KEY); + html = await this.request(url); + } + let d = []; + let items = pdfa(html, '#jieqi_page_contents .c_row') || []; + for (let item of items) { + let title = pdfh(item, '.c_subject a&&Text'); + let itemUrl = pd(item, '.c_subject a&&href'); + if (!title || !itemUrl) continue; + itemUrl = itemUrl.startsWith('http') ? itemUrl : this.host + itemUrl; + let pic = pd(item, 'img&&src') || ''; + pic = pic.startsWith('http') ? pic : this.host + pic; + d.push({ + title: title, + url: itemUrl, + desc: pdfh(item, '.c_tag span:eq(1)&&Text') || '', + pic_url: pic, + content: '', + }); + } + return setResult(d); + }, + + lazy: async function () { + let {input, pdfh} = this; + let html = await this.request(input); + let title = pdfh(html, 'h1&&Text') || ''; + let content = pdfh(html, '#acontent&&Html') || ''; + if (content) { + content = content.replace(/]*?>.*?<\/script>/gs, '') + .replace(/<\/p>/g, '\n\n') + .replace(/]*?>/g, '\n') + .replace(/<[^>]*?>/g, '') + .replace(/去读书推荐各位书友阅读:.*|去读书 www\.qudushu\.la|如果您中途有事离开,请按.*以便以后接着观看!/g, '') + .replace(/[()]/g, '') + .replace(/ /g, ' ') + .replace(/[ \t]+/g, ' ') + .replace(/\n[ \t]+|[ \t]+\n/g, '\n') + .replace(/\n+/g, '\n\n') + .trim(); + } + return { + parse: 0, + url: 'novel://' + JSON.stringify({title, content}), + js: '' + }; + } +}; diff --git "a/spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" "b/spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" new file mode 100644 index 00000000..40f61d11 --- /dev/null +++ "b/spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" @@ -0,0 +1,160 @@ +var rule = { + 类型: '小说', + author: 'EylinSir', + title: '阅读助手[书]', + desc: '阅读助手小说源', + host: 'https://api-bc.wtzw.com', + homeUrl: 'https://api-bc.wtzw.com', + url: '/api/v4/category/get-list?gender=fyclass&category_id=fyfilter&need_filters=1&page=fypage&need_category=1', + class_name: '男生&女生&出版', + class_url: '1&2&3', + searchUrl: '/api/v5/search/words?gender=3&imei_ip=2937357107&page=fypage&wd=**', + searchable: 2, + quickSearch: 0, + filterable: 1, + filter: { + "1": [{key: "type", name: "类型", value: [{"n":"玄幻奇幻","v":"202"},{"n":"都市人生","v":"203"},{"n":"武侠仙侠","v":"205"},{"n":"历史军事","v":"56"},{"n":"科幻末世","v":"64"},{"n":"游戏竞技","v":"75"},{"n":"体育赛事","v":"206"},{"n":"奇闻异事","v":"204"}]}], + "2": [{key: "type", name: "类型", value: [{"n":"现代言情","v":"1"},{"n":"古代言情","v":"2"},{"n":"幻想言情","v":"4"},{"n":"宫闱宅斗","v":"209"}]}], + "3": [{key: "type", name: "类型", value: [{"n":"悬疑推理","v":"262"},{"n":"文学艺术","v":"240"},{"n":"历史传记","v":"264"}]}] + }, + filter_url: "{{fl.type}}", + filter_def: {}, + headers: {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'}, + sign_headers: { + "app-version": "51110", "platform": "android", "reg": "0", "AUTHORIZATION": "", + "application-id": "com.****.reader", "net-env": "1", "channel": "unknown", "qm-params": "" + }, + timeout: 10000, + play_parse: true, + + request: async function (url, obj) { + obj = obj || {}; + const response = await _fetch(url, { + method: obj.method || 'GET', + headers: obj.headers || this.headers + }); + return response.text(); + }, + + 预处理: async function () { + this.sign_headers.sign = getSignStr(this.sign_headers); + }, + + 一级: async function (tid, pg, filter, extend) { + let d = []; + const cateMap = {'1':'202', '2':'1', '3':'262'}; + let gender = tid !== '-1' ? tid : '2'; + let category_id = cateMap[gender]; + const validSubTypes = ['202','203','205','56','64','75','206','204','1','2','4','209','262','240','264']; + if (extend?.type && validSubTypes.includes(extend.type)) { + category_id = extend.type; + } else if (filter && validSubTypes.includes(filter)) { + category_id = filter; + } + let params = { + gender: gender, + category_id: category_id, + need_filters: '1', + page: pg || '1', + need_category: '1', + imei_ip: '2937357107' + }; + params.sign = getSignStr(params); + let html = await this.request(buildUrl(`${this.host}/api/v4/category/get-list`, params), {headers: this.sign_headers}); + let json = JSON.parse(html); + if (json?.data?.books) { + d = json.data.books.map(it => ({ + title: it.title, + url: `${this.host}/api/v4/book/detail?id=${it.id}`, + desc: it.author, + pic_url: it.image_link, + content: it.intro + })); + } + return setResult(d); + }, + + 二级: async function () { + let VOD = {}; + let bookId = this.input.match(/id=(\d+)/)[1]; + let detailParams = {id: bookId, imei_ip: '2937357107', teeny_mode: '0'}; + detailParams.sign = getSignStr(detailParams); + let detailHtml = await this.request(buildUrl(`${this.host}/api/v4/book/detail`, detailParams), {headers: this.sign_headers}); + let detailJson = JSON.parse(detailHtml); + if (detailJson?.data?.book) { + let book = detailJson.data.book; + VOD = { + vod_name: book.title, + type_name: book.book_tag_list?.map(tag => tag.title).join(',') || '', + vod_pic: book.image_link, + vod_content: book.intro, + vod_remarks: book.latest_chapter_title, + vod_year: '', vod_area: '', + vod_actor: book.author, vod_director: book.author, + vod_play_from: '阅读助手' + }; + let tocParams = {id: book.id}; + tocParams.sign = getSignStr(tocParams); + let tocHtml = await this.request(buildUrl('https://api-ks.wtzw.com/api/v1/chapter/chapter-list', tocParams), {headers: this.sign_headers}); + let tocJson = JSON.parse(tocHtml); + if (tocJson?.data?.chapter_lists) { + VOD.vod_play_url = tocJson.data.chapter_lists.map(chapter => + `${chapter.title}$${book.id}@@${chapter.id}@@${chapter.title}` + ).join('#'); + } + } + return VOD; + }, + + 搜索: async function () { + let d = []; + let params = { + gender: '3', imei_ip: '2937357107', + page: this.MY_PAGE, wd: this.KEY + }; + params.sign = getSignStr(params); + let html = await this.request(buildUrl(`${this.host}/api/v5/search/words`, params), {headers: this.sign_headers}); + let json = JSON.parse(html); + if (json?.data?.books) { + d = json.data.books.map(it => ({ + title: it.original_title, + desc: it.author, + pic_url: it.image_link, + url: `${this.host}/api/v4/book/detail?id=${it.id}`, + content: it.intro + })); + } + return setResult(d); + }, + + lazy: async function () { + let [bookId, chapterId, title] = this.input.split('@@'); + let content = '内容加载失败'; + let params = {id: bookId, chapterId}; + params.sign = getSignStr(params); + let html = await this.request(buildUrl('https://api-ks.wtzw.com/api/v1/chapter/content', params), {headers: this.sign_headers}); + let json = JSON.parse(html); + if (json?.data?.content) content = decodeContent(json.data.content); + return { + parse: 0, + url: `novel://${JSON.stringify({title, content})}`, + js: '' + }; + } +}; + +function getSignStr(params) { + const sign_key = "d3dGiJc651gSQ8w1"; + return md5(Object.keys(params).sort().reduce((pre, n) => pre + n + "=" + params[n], "") + sign_key); +} + +function decodeContent(content) { + let key = CryptoJS.enc.Utf8.parse("242ccb8230d709e1"); + let ivEncData = CryptoJS.enc.Base64.parse(content); + let iv = CryptoJS.lib.WordArray.create(ivEncData.words.slice(0, 4)); + let encrypted = CryptoJS.lib.WordArray.create(ivEncData.words.slice(4)); + let decrypted = CryptoJS.AES.decrypt({ciphertext: encrypted}, key, { + iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 + }); + return decrypted.toString(CryptoJS.enc.Utf8); +} \ No newline at end of file From 08b37be00cc6b53184608ac1ade6b33cdabcb0fe Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Fri, 16 Jan 2026 00:12:49 +0800 Subject: [PATCH 027/101] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=89=E4=B8=AA?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\345\212\250\346\274\253[\346\274\253].js" | 105 ----- ...\346\274\253\345\246\226[\346\274\253].js" | 89 ---- ...51\347\251\272\345\275\261\350\247\206.py" | 428 ------------------ 3 files changed, 622 deletions(-) delete mode 100644 "spider/catvod/\351\243\216\350\275\246\345\212\250\346\274\253[\346\274\253].js" delete mode 100644 "spider/js/\345\212\250\346\274\253\345\246\226[\346\274\253].js" delete mode 100644 "spider/py/\345\244\251\347\251\272\345\275\261\350\247\206.py" diff --git "a/spider/catvod/\351\243\216\350\275\246\345\212\250\346\274\253[\346\274\253].js" "b/spider/catvod/\351\243\216\350\275\246\345\212\250\346\274\253[\346\274\253].js" deleted file mode 100644 index 0d1fa82a..00000000 --- "a/spider/catvod/\351\243\216\350\275\246\345\212\250\346\274\253[\346\274\253].js" +++ /dev/null @@ -1,105 +0,0 @@ -/* -@header({ - searchable: 1, - filterable: 1, - quickSearch: 1, - title: '风车动漫', - lang: 'cat' -}) -*/ -import {urljoin, parseList, parseDetail, lazy, request, cheerio, CryptoJS} from "./_dsutil.js"; - -const host = 'https://www.dmla5.com'; - -function init(cfg) { - const ext = cfg.ext; -} - -async function home(filter) { - let html = await request(host); - const $ = cheerio.load(html); - const listItems = $('.stui-header__menu li:gt(0):lt(4)'); - let classes = []; - listItems.each((index, element) => { - const item = $(element); - // 提取数据 - const type_name = item.find('a').text().trim(); - const type_id = urljoin(host, item.find('a').attr('href')).match(/.*\/(.*?)\.html/)[1]; - - classes.push({ - type_name, - type_id, - }); - }); - let res = { - 'class': classes - }; - return JSON.stringify(res); -} - -async function homeVod(params) { - let html = await request(host); - const $ = cheerio.load(html); - const listItems = $('ul.stui-vodlist.clearfix li'); - const d = parseList($, host, listItems); - - return JSON.stringify({ - list: d - }); -} - -async function category(tid, pg, filter, extend) { - let url = `${host}/type/${tid}-${pg}.html`; - let html = await request(url); - const $ = cheerio.load(html); - const listItems = $('.stui-vodlist li'); - const d = parseList($, host, listItems); - - return JSON.stringify({ - list: d - }); -} - -async function detail(id) { - let url = urljoin(host, id); - let html = await request(url); - const $ = cheerio.load(html); - - const vod = parseDetail($, host, url); - return JSON.stringify({ - list: [vod] - }) -} - -async function play(flag, id, flags) { - console.log("play"); - return await lazy(urljoin(host, id)); -} - -async function search(wd, quick, pg) { - let url = `${host}/search/${wd}----------${pg}---.html`; - let html = await request(url); - const $ = cheerio.load(html); - const listItems = $('ul.stui-vodlist__media li'); - const d = parseList($, host, listItems); - - return JSON.stringify({ - list: d - }); -} - -function proxy(params) { - return [200, 'text/plain;charset=utf-8', 'ok', null]; -} - -// 导出函数对象 -export default { - init: init, - home: home, - homeVod: homeVod, - category: category, - detail: detail, - play: play, - search: search, - proxy: proxy, -} \ No newline at end of file diff --git "a/spider/js/\345\212\250\346\274\253\345\246\226[\346\274\253].js" "b/spider/js/\345\212\250\346\274\253\345\246\226[\346\274\253].js" deleted file mode 100644 index 230e9798..00000000 --- "a/spider/js/\345\212\250\346\274\253\345\246\226[\346\274\253].js" +++ /dev/null @@ -1,89 +0,0 @@ -/* -@header({ - searchable: 2, - filterable: 1, - quickSearch: 1, - title: '动漫豆', - author: '', - '类型': '动漫', - lang: 'ds' -}) -*/ - -var rule = { - author: '', - title: '动漫豆', - 类型: '动漫', - host: 'https://www.dmyao.com/', - searchable: 2, - quickSearch: 1, - filterable: 1, - headers: { - 'User-Agent': 'MOBILE_UA' - }, - url: '/s/fyfilter.html', - filter_url: '{{fl.cateId or "fyclass"}}-{{fl.area}}-{{fl.by}}-{{fl.class}}-{{fl.lang}}-{{fl.letter}}---fypage---{{fl.year}}', - detailUrl: '/show/fyid.html', - searchUrl: '/search/**----------fypage---.html', - class_name: '国产动漫&日韩动漫&欧美动漫&港台动漫&动漫电影', - class_url: 'cnanime&jpanime&ouanime&hkanime&animevod', - play_parse: true, - 推荐: '*', - 一级: '.module-items.module-poster-items-base a;a&&title;.lazyload&&data-original;.module-item-note&&Text;a&&href', - 二级: { - "title": "h1&&Text", - "img": ".module-info-pic&&img&&src", - "desc": ".module-info-item:contains(备注)&&Text;.module-info-tag-link:contains(动画)&&Text;.module-info-tag-link:contains(大陆)&&Text;.module-info-item:contains(主演) .module-info-item-content&&Text;.module-info-item:contains(导演) .module-info-item-content&&Text", - "content": ".module-info-introduction-content&&Text", - "tabs": ".module-tab-items-box&&span", - "lists": ".module-play-list-base:eq(#id) a" - }, - - 搜索: '.module-card-item.module-item;a&&title;.lazyload&&data-original;.module-item-note&&Text;a&&href', - - lazy: async function lazyFunc() { - let html = await request(input); - let kcode = JSON.parse(html.split('aaaa=')[1].split('<')[0]); - let kurl = kcode.url; - - if (/\.(m3u8|mp4)/.test(kurl)) { - input = { - jx: 0, - parse: 0, - url: kurl, - header: { - 'User-Agent': MOBILE_UA, - 'Referer': getHome(kurl) - } - }; - } else { - input = { - jx: 0, - parse: 1, - url: input - }; - } - }, - - filter_def: { - cnanime: { - cateId: 'cnanime' - }, - jpanime: { - cateId: 'jpanime' - }, - ouanime: { - cateId: 'ouanime' - }, - hkanime: { - cateId: 'hkanime' - }, - animevod: { - cateId: 'animevod' - },hongkong: { - cateId: 'hongkong' - } - }, - - filter: {"cnanime":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"搞笑","v":"搞笑"},{"n":"运动","v":"运动"},{"n":"励志","v":"励志"},{"n":"热血","v":"热血"},{"n":"战斗","v":"战斗"},{"n":"竞技","v":"竞技"},{"n":"校园","v":"校园"},{"n":"青春","v":"青春"},{"n":"爱情","v":"爱情"},{"n":"冒险","v":"冒险"},{"n":"后宫","v":"后宫"},{"n":"百合","v":"百合"},{"n":"治愈","v":"治愈"},{"n":"萝莉","v":"萝莉"},{"n":"魔法","v":"魔法"},{"n":"悬疑","v":"悬疑"},{"n":"推理","v":"推理"},{"n":"奇幻","v":"奇幻"},{"n":"神魔","v":"神魔"},{"n":"恐怖","v":"恐怖"},{"n":"血腥","v":"血腥"},{"n":"机战","v":"机战"},{"n":"战争","v":"战争"},{"n":"犯罪","v":"犯罪"},{"n":"剧情","v":"剧情"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2025","v":"2025"},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"},{"n":"2007","v":"2007"},{"n":"2006","v":"2006"},{"n":"2005","v":"2005"},{"n":"2004","v":"2004"},{"n":"2003","v":"2003"},{"n":"2002","v":"2002"},{"n":"2001","v":"2001"},{"n":"2000","v":"2000"},{"n":"1999","v":"1999"},{"n":"1998","v":"1998"},{"n":"1997","v":"1997"},{"n":"1996","v":"1996"},{"n":"1995","v":"1995"},{"n":"1994","v":"1994"},{"n":"1993","v":"1993"},{"n":"1992","v":"1992"},{"n":"1991","v":"1991"},{"n":"1990","v":"1990"},{"n":"1989","v":"1989"},{"n":"1988","v":"1988"},{"n":"1987","v":"1987"},{"n":"1986","v":"1986"},{"n":"1985","v":"1985"},{"n":"1984","v":"1984"},{"n":"1980","v":"1980"},{"n":"1970","v":"1970"}]},{"key":"by","name":"排序","value":[{"n":"时间排序","v":"time"},{"n":"人气排序","v":"hits"},{"n":"评分排序","v":"score"}]}],"jpanime":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"搞笑","v":"搞笑"},{"n":"运动","v":"运动"},{"n":"励志","v":"励志"},{"n":"热血","v":"热血"},{"n":"战斗","v":"战斗"},{"n":"竞技","v":"竞技"},{"n":"校园","v":"校园"},{"n":"青春","v":"青春"},{"n":"爱情","v":"爱情"},{"n":"冒险","v":"冒险"},{"n":"后宫","v":"后宫"},{"n":"百合","v":"百合"},{"n":"治愈","v":"治愈"},{"n":"萝莉","v":"萝莉"},{"n":"魔法","v":"魔法"},{"n":"悬疑","v":"悬疑"},{"n":"推理","v":"推理"},{"n":"奇幻","v":"奇幻"},{"n":"神魔","v":"神魔"},{"n":"恐怖","v":"恐怖"},{"n":"血腥","v":"血腥"},{"n":"机战","v":"机战"},{"n":"战争","v":"战争"},{"n":"犯罪","v":"犯罪"},{"n":"剧情","v":"剧情"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2025","v":"2025"},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"},{"n":"2007","v":"2007"},{"n":"2006","v":"2006"},{"n":"2005","v":"2005"},{"n":"2004","v":"2004"},{"n":"2003","v":"2003"},{"n":"2002","v":"2002"},{"n":"2001","v":"2001"},{"n":"2000","v":"2000"},{"n":"1999","v":"1999"},{"n":"1998","v":"1998"},{"n":"1997","v":"1997"},{"n":"1996","v":"1996"},{"n":"1995","v":"1995"},{"n":"1994","v":"1994"},{"n":"1993","v":"1993"},{"n":"1992","v":"1992"},{"n":"1991","v":"1991"},{"n":"1990","v":"1990"},{"n":"1989","v":"1989"},{"n":"1988","v":"1988"},{"n":"1987","v":"1987"},{"n":"1986","v":"1986"},{"n":"1985","v":"1985"},{"n":"1984","v":"1984"},{"n":"1980","v":"1980"},{"n":"1970","v":"1970"}]},{"key":"by","name":"排序","value":[{"n":"时间排序","v":"time"},{"n":"人气排序","v":"hits"},{"n":"评分排序","v":"score"}]}],"ouanime":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"搞笑","v":"搞笑"},{"n":"运动","v":"运动"},{"n":"励志","v":"励志"},{"n":"热血","v":"热血"},{"n":"战斗","v":"战斗"},{"n":"竞技","v":"竞技"},{"n":"校园","v":"校园"},{"n":"青春","v":"青春"},{"n":"爱情","v":"爱情"},{"n":"冒险","v":"冒险"},{"n":"后宫","v":"后宫"},{"n":"百合","v":"百合"},{"n":"治愈","v":"治愈"},{"n":"萝莉","v":"萝莉"},{"n":"魔法","v":"魔法"},{"n":"悬疑","v":"悬疑"},{"n":"推理","v":"推理"},{"n":"奇幻","v":"奇幻"},{"n":"神魔","v":"神魔"},{"n":"恐怖","v":"恐怖"},{"n":"血腥","v":"血腥"},{"n":"机战","v":"机战"},{"n":"战争","v":"战争"},{"n":"犯罪","v":"犯罪"},{"n":"剧情","v":"剧情"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2025","v":"2025"},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"},{"n":"2007","v":"2007"},{"n":"2006","v":"2006"},{"n":"2005","v":"2005"},{"n":"2004","v":"2004"},{"n":"2003","v":"2003"},{"n":"2002","v":"2002"},{"n":"2001","v":"2001"},{"n":"2000","v":"2000"},{"n":"1999","v":"1999"},{"n":"1998","v":"1998"},{"n":"1997","v":"1997"},{"n":"1996","v":"1996"},{"n":"1995","v":"1995"},{"n":"1994","v":"1994"},{"n":"1993","v":"1993"},{"n":"1992","v":"1992"},{"n":"1991","v":"1991"},{"n":"1990","v":"1990"},{"n":"1989","v":"1989"},{"n":"1988","v":"1988"},{"n":"1987","v":"1987"},{"n":"1986","v":"1986"},{"n":"1985","v":"1985"},{"n":"1984","v":"1984"},{"n":"1980","v":"1980"},{"n":"1970","v":"1970"}]},{"key":"by","name":"排序","value":[{"n":"时间排序","v":"time"},{"n":"人气排序","v":"hits"},{"n":"评分排序","v":"score"}]}],"hkanime":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"搞笑","v":"搞笑"},{"n":"运动","v":"运动"},{"n":"励志","v":"励志"},{"n":"热血","v":"热血"},{"n":"战斗","v":"战斗"},{"n":"竞技","v":"竞技"},{"n":"校园","v":"校园"},{"n":"青春","v":"青春"},{"n":"爱情","v":"爱情"},{"n":"冒险","v":"冒险"},{"n":"后宫","v":"后宫"},{"n":"百合","v":"百合"},{"n":"治愈","v":"治愈"},{"n":"萝莉","v":"萝莉"},{"n":"魔法","v":"魔法"},{"n":"悬疑","v":"悬疑"},{"n":"推理","v":"推理"},{"n":"奇幻","v":"奇幻"},{"n":"神魔","v":"神魔"},{"n":"恐怖","v":"恐怖"},{"n":"血腥","v":"血腥"},{"n":"机战","v":"机战"},{"n":"战争","v":"战争"},{"n":"犯罪","v":"犯罪"},{"n":"剧情","v":"剧情"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2025","v":"2025"},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"},{"n":"2007","v":"2007"},{"n":"2006","v":"2006"},{"n":"2005","v":"2005"},{"n":"2004","v":"2004"},{"n":"2003","v":"2003"},{"n":"2002","v":"2002"},{"n":"2001","v":"2001"},{"n":"2000","v":"2000"},{"n":"1999","v":"1999"},{"n":"1998","v":"1998"},{"n":"1997","v":"1997"},{"n":"1996","v":"1996"},{"n":"1995","v":"1995"},{"n":"1994","v":"1994"},{"n":"1993","v":"1993"},{"n":"1992","v":"1992"},{"n":"1991","v":"1991"},{"n":"1990","v":"1990"},{"n":"1989","v":"1989"},{"n":"1988","v":"1988"},{"n":"1987","v":"1987"},{"n":"1986","v":"1986"},{"n":"1985","v":"1985"},{"n":"1984","v":"1984"},{"n":"1980","v":"1980"},{"n":"1970","v":"1970"}]},{"key":"by","name":"排序","value":[{"n":"时间排序","v":"time"},{"n":"人气排序","v":"hits"},{"n":"评分排序","v":"score"}]}],"animevod":[{"key":"class","name":"剧情","value":[{"n":"全部","v":""},{"n":"搞笑","v":"搞笑"},{"n":"运动","v":"运动"},{"n":"励志","v":"励志"},{"n":"热血","v":"热血"},{"n":"战斗","v":"战斗"},{"n":"竞技","v":"竞技"},{"n":"校园","v":"校园"},{"n":"青春","v":"青春"},{"n":"爱情","v":"爱情"},{"n":"冒险","v":"冒险"},{"n":"后宫","v":"后宫"},{"n":"百合","v":"百合"},{"n":"治愈","v":"治愈"},{"n":"萝莉","v":"萝莉"},{"n":"魔法","v":"魔法"},{"n":"悬疑","v":"悬疑"},{"n":"推理","v":"推理"},{"n":"奇幻","v":"奇幻"},{"n":"神魔","v":"神魔"},{"n":"恐怖","v":"恐怖"},{"n":"血腥","v":"血腥"},{"n":"机战","v":"机战"},{"n":"战争","v":"战争"},{"n":"犯罪","v":"犯罪"},{"n":"剧情","v":"剧情"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2025","v":"2025"},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"},{"n":"2007","v":"2007"},{"n":"2006","v":"2006"},{"n":"2005","v":"2005"},{"n":"2004","v":"2004"},{"n":"2003","v":"2003"},{"n":"2002","v":"2002"},{"n":"2001","v":"2001"},{"n":"2000","v":"2000"},{"n":"1999","v":"1999"},{"n":"1998","v":"1998"},{"n":"1997","v":"1997"},{"n":"1996","v":"1996"},{"n":"1995","v":"1995"},{"n":"1994","v":"1994"},{"n":"1993","v":"1993"},{"n":"1992","v":"1992"},{"n":"1991","v":"1991"},{"n":"1990","v":"1990"},{"n":"1989","v":"1989"},{"n":"1988","v":"1988"},{"n":"1987","v":"1987"},{"n":"1986","v":"1986"},{"n":"1985","v":"1985"},{"n":"1984","v":"1984"},{"n":"1980","v":"1980"},{"n":"1970","v":"1970"}]},{"key":"by","name":"排序","value":[{"n":"时间排序","v":"time"},{"n":"人气排序","v":"hits"},{"n":"评分排序","v":"score"}]}]} -} \ No newline at end of file diff --git "a/spider/py/\345\244\251\347\251\272\345\275\261\350\247\206.py" "b/spider/py/\345\244\251\347\251\272\345\275\261\350\247\206.py" deleted file mode 100644 index b8ac80bf..00000000 --- "a/spider/py/\345\244\251\347\251\272\345\275\261\350\247\206.py" +++ /dev/null @@ -1,428 +0,0 @@ -""" -@header({ - searchable: 1, - filterable: 1, - quickSearch: 1, - title: '天空影视', - lang: 'hipy' -}) -""" - -from Crypto.PublicKey import RSA -from Crypto.Util.Padding import pad -from Crypto.Cipher import AES, PKCS1_v1_5 -import sys,time,json,base64,urllib3,hashlib -urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) -sys.path.append('..') -try: - # from base.spider import Spider as BaseSpider - from base.spider import BaseSpider -except ImportError: - from t4.base.spider import BaseSpider - -class Spider(BaseSpider): - host, android_id, init_sign_salt, app_cert_sha1, private_key, token, timeout, headers = ('','','','','','','', - { - 'User-Agent': "okhttp-okgo/jeasonlzy", - 'Connection': "Keep-Alive", - 'Accept-Encoding': "gzip", - 'Accept-Language': "zh-CN,zh;q=0.8", - 'sign': "", - 'devicename': "Xiaomi 15", - 'deviceos': "15", - 'bundleid': "", - 'versionname': "2.1.0", - 'versioncode': "2001000", - 'vendor': "Xiaomi", - 'chid': "26002", - 'subchid': "26002", - 'os': "1", - 'screenpx': "2670*1200", - 'nettype': "wifi", - 'audit': "1", - 'force': "1" - }) - - def init(self, extend=''): - try: - config = json.loads(extend) - except (json.JSONDecodeError, TypeError): - config = {} - self.timeout = config.get('timeout', 15) - self.host = config.get('host', 'http://api-live.vfilm.life') - self.android_id = config.get('android_id', '6617a62678360a86') - self.init_sign_salt = config.get('init_sign_salt', 'lsdfnrtpmslscndy') - self.app_cert_sha1 = config.get('app_cert_sha1', '70:27:C9:DC:98:96:75:CD:35:DB:0C:CE:AC:CA:84:0A:B7:1E:B5:7F') - self.private_key = config.get('private_key', 'MIICWwIBAAKBgQDYJzTUOgYdR/eIhsjpNMYWQGYl3pBycwKDoL6KThpPwrZQ9+xv\nLSaPj92HQknVaWR/RD6tHVRysChoeqAFyyQUe4UXAYnJDNlurpELb5HUIBFgmO97\niIOJCK6zbmnHT6WOHYaODTqrmX6NBgLjoFiDYBPYxG1T/K1uZ47xQDHFQQIDAQAB\nAoGAEpT8Q6phUC8ZppD/wJya0tribSr++/fLJYmyF62zMVwp1DgcCUq2X+0cPD6E\nnmYbD53MTZGR6vId5y1ziEv4Y+nu5EUyDk1xeGIxojpLhxuRoCbBt+LMJ1YUxv6p\n6F4SNwQ10U78m829Ud50mJBvkt2Vg8607SUrWheydvWHyAECQQDvayhgX5XEFaha\nUtPp5pPIkKBqHnLGm4et8be/jIIFhY9CIJbKLsqc0OFwNvz46GtRQwrtHP7LxTEF\nYT0C6CahAkEA5x+OqN/iykZIHc6Z2qZfAiLjPnQJu9DTXC/kt3TlsCc3XPNkXlAu\nq786LluH6dzQfDbLpmODtzNWavfgCtE6oQJAdTsJKDdlg//+0UthTFSE5F48zfle\nxfT9+KQ1Duvj9oQxY3XFn/ZNa3+0A1hJgi977Oxg+z2JXYmOuU2lrDi0QQJAMWwA\nF4B4gIRy21zYbXbyDgTjzvEFO9I1wBrFr60hiH96STgKmFhRAozLpioQcCO1uToG\nZjgVbFFgA1Op5uZCwQJAL1ziHIphaoCpHnnESidt3Nlrzqj/5uEpdHu7ZvPuZYya\nU8e1AhjeP+zKvfJUiXwDGuDZLx5Xe0BK8Bu72sdKcQ==') - self.headers['bundleid'] = config.get('bundleid', 'com.ytwl.fhtq') - self.token = config.get('token', '') - imsi_id = config.get('imsi_id', '1') - self.headers['sign'] = self.sign_encrypt(f'jing##&&&wei##&&&fuwu##{imsi_id}&&&idian##&&&she##{self.android_id}&&&mdian##{self.android_id}&&&olian##&&&an##{self.android_id}') - - def homeContent(self, filter): - if not self.host: return None - timestamp = self.timestamp() - payload = { - 'applock': "0", - 'ncode': self.init_sign(timestamp), - 'force': "1", - 'retime': timestamp - } - response = self.post(f'{self.host}/news/tv/columns', data=payload, headers=self.headers, timeout=self.timeout, verify=False).json() - classes = [] - for i in response['data']['list']: - if i['is_show_recommend'] == 1: - home_class_id = i.get('column_id') - continue - classes.append({'type_id': i['column_id'], 'type_name': i['name']}) - timestamp = self.timestamp() - payload = { - 'column_id': home_class_id or '164', - 'ncode': self.init_sign(timestamp), - 'page': "1", - 'retime': timestamp - } - response = self.post(f'{self.host}/news/tv/sectionsPageByColumn', data=payload, headers=self.headers, timeout=self.timeout, verify=False).json() - section_list = response['data']['section_list'] - videos = [] - for i in section_list: - for j in i.get('tv_list', []): - videos.append({ - 'vod_id': j.get('news_id'), - 'vod_name': j.get('title', j.get('sub_title')), - 'vod_pic': j.get('ver_pic') - }) - return {'class': classes, 'list': videos} - - def categoryContent(self, tid, pg, filter, extend): - timestamp = self.timestamp() - payload = { - 'column_id': tid, - 'ncode': self.init_sign(timestamp), - 'page': pg, - 'retime': timestamp - } - response = self.post(f'{self.host}/news/tv/tvListByColumn', data=payload, headers=self.headers, timeout=self.timeout, verify=False).json() - videos = [] - for i in response['data']['list']: - up_count = i.get('up_count', '') - if up_count: - up_count = f'{up_count}集' - videos.append({ - 'vod_id': i.get('news_id'), - 'vod_name': i.get('title'), - 'vod_pic': i.get('ver_pic'), - 'vod_remarks': up_count, - 'vod_area': i.get('area'), - 'vod_class': i.get('cat'), - 'vod_score': i.get('score'), - 'vod_year': i.get('pubdate') - }) - return {'list': videos, 'page': pg} - - def searchContent(self, key, quick, pg='1'): - timestamp = self.timestamp() - payload = { - 'ncode': self.init_sign(timestamp), - 'signKey': self.signKey(timestamp), - 'page': pg, - 'is_check': "0", - 'keyword': key, - 'retime': timestamp - } - response = self.post(f'{self.host}/search/wordinfo', data=payload, headers=self.headers, timeout=self.timeout, verify=False).json() - videos = [] - for i in response['data']['search_list']: - for j in i.get('list',[]): - vod_remarks = j.get('up_count') - if vod_remarks: - vod_remarks = f'{vod_remarks}集' - else: - vod_remarks = j.get('news_type_name') - videos.append({ - 'vod_id': j.get('news_id'), - 'vod_name': j.get('origin_title',j.get('title')), - 'vod_pic': j.get('ver_pic'), - 'vod_content': j.get('desc'), - 'vod_remarks': vod_remarks, - 'vod_area': j.get('area'), - }) - return {'list': videos, 'page': pg} - - def detailContent(self, ids): - timestamp = self.timestamp() - payload = { - 'ncode': self.init_sign(timestamp), - 'signKey': self.signKey(timestamp), - 'news_id': ids[0], - 'retime': timestamp - } - response = self.post(f'{self.host}/news/tv/detail', data=payload, headers=self.headers, timeout=self.timeout, verify=False).json() - data = response['data'] - timestamp2 = self.timestamp() - payload = { - 'next': "0", - 'pl_id': "", - 'playlink_num': "1", - 'ncode': self.init_sign(timestamp2), - 'format': "high", - 'mobile': "", - 'check': "0", - 'mpl_id': "", - 'news_id': ids[0], - 'retime': timestamp2, - 'resite': "", - 'signKey': self.signKey(timestamp2), - 'bid': "300", - 'retry': "0" - } - response = self.post(f'{self.host}/news/tv/multiDetail', data=payload, headers=self.headers, timeout=self.timeout, verify=False).json() - data_ = response['data']['data'] - data2_ = self.decrypt(data_) - data2 = json.loads(data2_) - max_up_count = data2.get('max_up_count',data2.get('up_count')) - news_id = data2['news_id'] - site_list_test = data2.get('test') - if site_list_test: - site_list = site_list_test.get('site_list',[]) - vod_play_froms = [] - vod_play_froms.extend(site_list) - vod_play_froms = [str(item) for item in vod_play_froms] - vod_play_urls = [] - for i in vod_play_froms: - urls = [] - for j in range(1,int(max_up_count) + 1): - urls.append(f"第{j}集${j}@{news_id}@{i}") - vod_play_urls.append('#'.join(urls)) - videos = [] - up_count = data.get('up_count',data.get('max_up_count')) - if up_count: - up_count = f'{up_count}集' - videos.append({ - 'vod_id': data.get('news_id'), - 'vod_name': data.get('title'), - 'vod_content': data.get('desc'), - 'vod_director': data.get('dir'), - 'vod_actor': data.get('act'), - 'vod_class': data.get('cat'), - 'vod_remarks': up_count, - 'vod_area': data.get('area'), - 'vod_play_from': '$$$'.join(vod_play_froms), - 'vod_play_url': '$$$'.join(vod_play_urls) - }) - return {'list': videos} - - def playerContent(self, flag, id, vipflags): - jx, url, play_header = 0, '', {'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 15; 24129PN74C Build/AP3A.240617.008)'} - episodes, news_id, resite = id.split('@', 2) - timestamp = self.timestamp() - payload = { - 'next': "0", - 'pl_id': "", - 'playlink_num': episodes, - 'ncode': self.init_sign(timestamp), - 'format': 'high', - 'mobile': "", - 'check': "0", - 'mpl_id': "", - 'news_id': news_id, - 'retime': timestamp, - 'resite': resite, - 'signKey': self.signKey(timestamp), - 'bid': '300', - 'retry': "0" - } - response = self.post(f'{self.host}/news/tv/multiDetail', data=payload, headers=self.headers,timeout=self.timeout, verify=False).json() - data_ = response['data']['data'] - data_ = self.decrypt(data_) - data = json.loads(data_) - url_list = data.get('url_list', []) - if url_list: - for i in url_list: - play_url = i.get('surl', '') - if play_url.startswith('http'): - url = play_url - break - if url: - return {'jx': 0, 'parse': 0, 'url': url, 'header': play_header} - cp_data = data['cp_data'] - wanneng = cp_data.get('wanneng', '') - parse_url = '' - if wanneng and isinstance(wanneng, dict): - parse_url = wanneng.get('postUrl', '') - type = cp_data.get('TYPE') - if type == 'DIRECT': - for i in cp_data['V']: - for j in i.values(): - if j.startswith(('http://', 'https://')): - play_url = j - break - if 'play_url' in locals() and play_url: - return {'jx': jx, 'parse': 0, 'url': play_url, 'header': play_header} - try: - if parse_url: - parse_data = self.fetch(parse_url, headers={'User-Agent': "okhttp/3.10.0", 'Accept-Encoding': "gzip"}, timeout=self.timeout, verify=False).text - except Exception: - return {'jx': 0, 'parse': 0, 'url': ''} - if not parse_data: - return {'jx': 0, 'parse': 0, 'url': ''} - timestamp2 = self.timestamp() - vid_format = data.get('format', 'high') - payload2 = { - 'pl_id': data.get('pl_id', ''), - 'is_down': data.get('is_down', '0'), - 'data': parse_data, - 'playlink_num': episodes, - 'ncode': self.init_sign(timestamp), - 'format': vid_format, - 'cp_id': data.get('cp_id', ''), - 'mpl_id': data.get('mpl_id', ''), - 'url': data['web_url'], - 'retime': timestamp2, - 'wn_info': json.dumps(data['cp_data'].get('wanneng', '')), - 'site': data['site'], - 'news_type': "null", - 'web_url': data['web_url'], - 'mc': "null", - 'bid': self.bid(vid_format) - } - response = self.post(f'{self.host}/parse/index/parse', data=payload2, headers=self.headers, timeout=self.timeout, verify=False).json() - data2_ = response['data']['data'] - data2_ = self.decrypt(data2_) - data2 = json.loads(data2_) - play_url = data2['video'][0]['url'] - if play_url.startswith('http'): - url = play_url - return {'jx': jx, 'parse': 0, 'url': url, 'header': play_header} - - def timestamp(self): - timestamp = time.time() - return str(int(round(timestamp * 1000))) - - def md5(self,str): - md5_hash = hashlib.md5() - md5_hash.update(str.encode('utf-8')) - return md5_hash.hexdigest() - - def init_sign(self, timestamp): - first_md5 = self.md5(f"{self.init_sign_salt}{self.token}{self.android_id}{timestamp}") - combined = first_md5[:10] + first_md5[22:] - return self.md5(combined) - - def get_strings(self, str_param, str2_param): - strlist = [ - "afv", "Cs", "D", "bd", "cs", "h", "i0", "j0", "K", "L", "M8", "N", "O", "P", "Q", "R", - "k", "l", "m", "n", "o", "p", "q", "r", "s", "t7", "Z", "A", "B", "E", "F", "G", "H", "I", - "J", "S16", "T", "d", "e", "f", "g", "U", "V", "W6", "u", "v", "w", "x", "y", "Xd", "Y", - "Za0", "gw", "Us", "Vd", "Wv", "X", "Y", "Zx4", "afv", "Cs", "D", "bd", "cs", "h", "i", - "j", "K0", "L", "M", "N", "O0", "P", "Q", "R", "k", "l1", "m", "n", "o", "p", "q", "r", - "s1", "t", "Z", "A", "B", "E", "F5", "G", "H", "I0", "J", "S", "T", "d", "e", "f", "g1", - "U1", "V", "W3", "u", "v2", "w", "x", "y", "Xd", "Y", "Za", "gw", "Us", "Vd", "Wv", "X", - "Y", "Zx" - ] - bytes_data = str_param.encode('utf-8') - as_list = strlist.copy() - if str2_param and len(str2_param) > 0: - for s in str2_param.split(','): - as_list.append(s) - sb = [] - for i in range(len(bytes_data)): - abs_val = abs(bytes_data[i] - i) % 100 - if abs_val < len(as_list): - sb.append(as_list[abs_val]) - return ''.join(sb) + "==" - - def send_increment_data(self, str_param, str2_param, str3_param=None): - bytes_data = str2_param.encode('utf-8') - sb = [] - loop_count = len(bytes_data) // 2 - for i in range(loop_count): - index = (len(bytes_data) - (i % 8)) - 1 - b = bytes_data[index] - sb.append(str(abs(bytes_data[i] - b) % 100)) - sb.append("$") - sb.append(str((bytes_data[(len(bytes_data) - 1) - i] + b) % 100)) - sb.append("$") - substring = ''.join(sb)[loop_count:] - strings = self.get_strings(substring, str3_param) - result = str_param + strings - return result - - def sign_encrypt(self,text): - key = "ZXJsaW5nZXJlcm5pYW5zaXl1ZWVyc2hp".encode('utf-8') - cipher = AES.new(key, AES.MODE_ECB) - text_bytes = text.encode('utf-8') - padded_text = pad(text_bytes, AES.block_size) - encrypted_bytes = cipher.encrypt(padded_text) - encrypted_base64 = base64.b64encode(encrypted_bytes).decode('utf-8') - return encrypted_base64 - - def decrypt(self, encrypted_data): - try: - private_key = self.private_key - if not private_key.startswith('-----'): - private_key = f'-----BEGIN RSA PRIVATE KEY-----\n{private_key}\n-----END RSA PRIVATE KEY-----' - private_key = RSA.importKey(private_key) - cipher = PKCS1_v1_5.new(private_key) - decoded_data = base64.b64decode(encrypted_data) - key_size = private_key.size_in_bytes() - decrypted_text_parts = [] - if len(decoded_data) > key_size: - i = 0 - while i < len(decoded_data): - chunk = decoded_data[i:i + key_size] - decrypted_chunk = cipher.decrypt(chunk, None) - if decrypted_chunk is None: - raise ValueError("解密失败,可能是数据损坏或密钥不匹配") - decrypted_text_parts.append(decrypted_chunk.decode('utf-8')) - i += key_size - else: - decrypted_data = cipher.decrypt(decoded_data, None) - if decrypted_data is None: - raise ValueError("解密失败,可能是数据损坏或密钥不匹配") - decrypted_text_parts.append(decrypted_data.decode('utf-8')) - return ''.join(decrypted_text_parts) - except Exception: - return None - - def signKey(self,timestamp): - return self.send_increment_data(timestamp, f'{self.android_id}{self.md5(self.app_cert_sha1)}{timestamp}') - - def bid(self, str_param): - str_to_c2 = { - "fluent": 2, "normal": 4, "super2": 15, "4K": 22, "4k": 23, "原画": 13, - "标清": 3, "极速": 1, "流畅": 0, "蓝光": 14, "超清": 9, "高清": 5, - "360P": 17, "360p": 16, "540P": 8, "540p": 7, "720P": 12, "720p": 11, - "high": 6, "1080P": 19, "1080p": 18, "1280P": 21, "1280p": 20, "super": 10 - } - result_mapping = [ - (0, 2, "200", "fluent"), (3, 4, "300", "normal"), (5, 8, "300", "high"), (9, 10, "500", "super"), - (11, 12, "400", "super2"), - (13, 15, "600", "super2"), (16, 17, "200", "normal"), (18, 19, "500", "super2"), (20, 21, "600", "super2"), - (22, 23, "800", "super2") - ] - if not str_param: - return {} - c2 = str_to_c2.get(str_param, 65535) - for min_val, max_val, bid, fmt in result_mapping: - if min_val <= c2 <= max_val: - return bid - return "300" - - def homeVideoContent(self): - pass - - def getName(self): - pass - - def isVideoFormat(self, url): - pass - - def manualVideoCheck(self): - pass - - def destroy(self): - pass - - def localProxy(self, param): - pass \ No newline at end of file From 06e8d5ab483513df2533d9606cef0e9ac5431b7b Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Fri, 16 Jan 2026 10:25:52 +0800 Subject: [PATCH 028/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=A3=B0=E6=BC=AB?= =?UTF-8?q?=E7=94=B5=E5=8F=B0[=E4=B9=A6].js=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\345\212\251\346\211\213[\344\271\246].js" | 173 ++---------------- 1 file changed, 13 insertions(+), 160 deletions(-) diff --git "a/spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" "b/spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" index 40f61d11..051389c6 100644 --- "a/spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" +++ "b/spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" @@ -1,160 +1,13 @@ -var rule = { - 类型: '小说', - author: 'EylinSir', - title: '阅读助手[书]', - desc: '阅读助手小说源', - host: 'https://api-bc.wtzw.com', - homeUrl: 'https://api-bc.wtzw.com', - url: '/api/v4/category/get-list?gender=fyclass&category_id=fyfilter&need_filters=1&page=fypage&need_category=1', - class_name: '男生&女生&出版', - class_url: '1&2&3', - searchUrl: '/api/v5/search/words?gender=3&imei_ip=2937357107&page=fypage&wd=**', - searchable: 2, - quickSearch: 0, - filterable: 1, - filter: { - "1": [{key: "type", name: "类型", value: [{"n":"玄幻奇幻","v":"202"},{"n":"都市人生","v":"203"},{"n":"武侠仙侠","v":"205"},{"n":"历史军事","v":"56"},{"n":"科幻末世","v":"64"},{"n":"游戏竞技","v":"75"},{"n":"体育赛事","v":"206"},{"n":"奇闻异事","v":"204"}]}], - "2": [{key: "type", name: "类型", value: [{"n":"现代言情","v":"1"},{"n":"古代言情","v":"2"},{"n":"幻想言情","v":"4"},{"n":"宫闱宅斗","v":"209"}]}], - "3": [{key: "type", name: "类型", value: [{"n":"悬疑推理","v":"262"},{"n":"文学艺术","v":"240"},{"n":"历史传记","v":"264"}]}] - }, - filter_url: "{{fl.type}}", - filter_def: {}, - headers: {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'}, - sign_headers: { - "app-version": "51110", "platform": "android", "reg": "0", "AUTHORIZATION": "", - "application-id": "com.****.reader", "net-env": "1", "channel": "unknown", "qm-params": "" - }, - timeout: 10000, - play_parse: true, - - request: async function (url, obj) { - obj = obj || {}; - const response = await _fetch(url, { - method: obj.method || 'GET', - headers: obj.headers || this.headers - }); - return response.text(); - }, - - 预处理: async function () { - this.sign_headers.sign = getSignStr(this.sign_headers); - }, - - 一级: async function (tid, pg, filter, extend) { - let d = []; - const cateMap = {'1':'202', '2':'1', '3':'262'}; - let gender = tid !== '-1' ? tid : '2'; - let category_id = cateMap[gender]; - const validSubTypes = ['202','203','205','56','64','75','206','204','1','2','4','209','262','240','264']; - if (extend?.type && validSubTypes.includes(extend.type)) { - category_id = extend.type; - } else if (filter && validSubTypes.includes(filter)) { - category_id = filter; - } - let params = { - gender: gender, - category_id: category_id, - need_filters: '1', - page: pg || '1', - need_category: '1', - imei_ip: '2937357107' - }; - params.sign = getSignStr(params); - let html = await this.request(buildUrl(`${this.host}/api/v4/category/get-list`, params), {headers: this.sign_headers}); - let json = JSON.parse(html); - if (json?.data?.books) { - d = json.data.books.map(it => ({ - title: it.title, - url: `${this.host}/api/v4/book/detail?id=${it.id}`, - desc: it.author, - pic_url: it.image_link, - content: it.intro - })); - } - return setResult(d); - }, - - 二级: async function () { - let VOD = {}; - let bookId = this.input.match(/id=(\d+)/)[1]; - let detailParams = {id: bookId, imei_ip: '2937357107', teeny_mode: '0'}; - detailParams.sign = getSignStr(detailParams); - let detailHtml = await this.request(buildUrl(`${this.host}/api/v4/book/detail`, detailParams), {headers: this.sign_headers}); - let detailJson = JSON.parse(detailHtml); - if (detailJson?.data?.book) { - let book = detailJson.data.book; - VOD = { - vod_name: book.title, - type_name: book.book_tag_list?.map(tag => tag.title).join(',') || '', - vod_pic: book.image_link, - vod_content: book.intro, - vod_remarks: book.latest_chapter_title, - vod_year: '', vod_area: '', - vod_actor: book.author, vod_director: book.author, - vod_play_from: '阅读助手' - }; - let tocParams = {id: book.id}; - tocParams.sign = getSignStr(tocParams); - let tocHtml = await this.request(buildUrl('https://api-ks.wtzw.com/api/v1/chapter/chapter-list', tocParams), {headers: this.sign_headers}); - let tocJson = JSON.parse(tocHtml); - if (tocJson?.data?.chapter_lists) { - VOD.vod_play_url = tocJson.data.chapter_lists.map(chapter => - `${chapter.title}$${book.id}@@${chapter.id}@@${chapter.title}` - ).join('#'); - } - } - return VOD; - }, - - 搜索: async function () { - let d = []; - let params = { - gender: '3', imei_ip: '2937357107', - page: this.MY_PAGE, wd: this.KEY - }; - params.sign = getSignStr(params); - let html = await this.request(buildUrl(`${this.host}/api/v5/search/words`, params), {headers: this.sign_headers}); - let json = JSON.parse(html); - if (json?.data?.books) { - d = json.data.books.map(it => ({ - title: it.original_title, - desc: it.author, - pic_url: it.image_link, - url: `${this.host}/api/v4/book/detail?id=${it.id}`, - content: it.intro - })); - } - return setResult(d); - }, - - lazy: async function () { - let [bookId, chapterId, title] = this.input.split('@@'); - let content = '内容加载失败'; - let params = {id: bookId, chapterId}; - params.sign = getSignStr(params); - let html = await this.request(buildUrl('https://api-ks.wtzw.com/api/v1/chapter/content', params), {headers: this.sign_headers}); - let json = JSON.parse(html); - if (json?.data?.content) content = decodeContent(json.data.content); - return { - parse: 0, - url: `novel://${JSON.stringify({title, content})}`, - js: '' - }; - } -}; - -function getSignStr(params) { - const sign_key = "d3dGiJc651gSQ8w1"; - return md5(Object.keys(params).sort().reduce((pre, n) => pre + n + "=" + params[n], "") + sign_key); -} - -function decodeContent(content) { - let key = CryptoJS.enc.Utf8.parse("242ccb8230d709e1"); - let ivEncData = CryptoJS.enc.Base64.parse(content); - let iv = CryptoJS.lib.WordArray.create(ivEncData.words.slice(0, 4)); - let encrypted = CryptoJS.lib.WordArray.create(ivEncData.words.slice(4)); - let decrypted = CryptoJS.AES.decrypt({ciphertext: encrypted}, key, { - iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 - }); - return decrypted.toString(CryptoJS.enc.Utf8); -} \ No newline at end of file +/* +@header({ + searchable: 2, + filterable: 1, + quickSearch: 0, + title: '阅读助手[书]', + author: 'EylinSir', + '类型': '小说', + lang: 'ds' +}) +*/ + +dmFyIHJ1bGUgPSB7CiAgICDnsbvlnos6ICflsI/or7QnLAogICAgYXV0aG9yOiAnRXlsaW5TaXInLAogICAgdGl0bGU6ICfpmIXor7vliqnmiYtb5LmmXScsCiAgICBkZXNjOiAn6ZiF6K+75Yqp5omL5bCP6K+05rqQJywKICAgIGhvc3Q6ICdodHRwczovL2FwaS1iYy53dHp3LmNvbScsCiAgICBjaGFwdGVySG9zdDogJ2h0dHBzOi8vYXBpLWtzLnd0encuY29tJywKICAgIGhvbWVVcmw6ICdodHRwczovL2FwaS1iYy53dHp3LmNvbScsCiAgICB1cmw6ICcvYXBpL3Y0L2NhdGVnb3J5L2dldC1saXN0P2dlbmRlcj1meWNsYXNzJmNhdGVnb3J5X2lkPWZ5ZmlsdGVyJm5lZWRfZmlsdGVycz0xJnBhZ2U9ZnlwYWdlJm5lZWRfY2F0ZWdvcnk9MScsCiAgICBjbGFzc19uYW1lOiAn55S355SfJuWls+eUnyblh7rniYgnLAogICAgY2xhc3NfdXJsOiAnMSYyJjMnLAogICAgc2VhcmNoVXJsOiAnL2FwaS92NS9zZWFyY2gvd29yZHM/Z2VuZGVyPTMmaW1laV9pcD0yOTM3MzU3MTA3JnBhZ2U9ZnlwYWdlJndkPSoqJywKICAgIHNlYXJjaGFibGU6IDIsCiAgICBxdWlja1NlYXJjaDogMCwKICAgIGZpbHRlcmFibGU6IDEsCiAgICBmaWx0ZXI6IHsKICAgICAgICAiMSI6IFt7a2V5OiAidHlwZSIsIG5hbWU6ICLnsbvlnosiLCB2YWx1ZTogW3sibiI6IueOhOW5u+Wlh+W5uyIsInYiOiIyMDIifSx7Im4iOiLpg73luILkurrnlJ8iLCJ2IjoiMjAzIn0seyJuIjoi5q2m5L6g5LuZ5L6gIiwidiI6IjIwNSJ9LHsibiI6IuWOhuWPsuWGm+S6iyIsInYiOiI1NiJ9LHsibiI6IuenkeW5u+acq+S4liIsInYiOiI2NCJ9LHsibiI6Iua4uOaIj+ernuaKgCIsInYiOiI3NSJ9LHsibiI6IuS9k+iCsui1m+S6iyIsInYiOiIyMDYifSx7Im4iOiLlpYfpl7vlvILkuosiLCJ2IjoiMjA0In1dfV0sCiAgICAgICAgIjIiOiBbe2tleTogInR5cGUiLCBuYW1lOiAi57G75Z6LIiwgdmFsdWU6IFt7Im4iOiLnjrDku6PoqIDmg4UiLCJ2IjoiMSJ9LHsibiI6IuWPpOS7o+iogOaDhSIsInYiOiIyIn0seyJuIjoi5bm75oOz6KiA5oOFIiwidiI6IjQifSx7Im4iOiLnp43nlLDnu4/llYYiLCJ2IjoiMTYifV19XSwKICAgICAgICAiMyI6IFt7a2V5OiAidHlwZSIsIG5hbWU6ICLnsbvlnosiLCB2YWx1ZTogW3sibiI6IuaWh+WtpuiJuuacryIsInYiOiIyNDAifSx7Im4iOiLkurrmlofnp5HnpL4iLCJ2IjoiMjQxIn0seyJuIjoi57uP566h5Yqx5b+XIiwidiI6IjI0MiJ9LHsibiI6Iue7j+WFuOaWh+WtpiIsInYiOiIyNDMifSx7Im4iOiLkurrniankvKDorrAiLCJ2IjoiMjQ3In0seyJuIjoi5bCR5YS/5pWZ6IKyIiwidiI6IjI1OCJ9LHsibiI6IuWPpOS7o+iogOaDhSIsInYiOiIyNTkifSx7Im4iOiLnjrDku6PoqIDmg4UiLCJ2IjoiMjYwIn0seyJuIjoi5oKs55aR5o6o55CGIiwidiI6IjI2MiJ9LHsibiI6IuWOhuWPsuS8oOiusCIsInYiOiIyNjQifSx7Im4iOiLpnZLmmKXmloflraYiLCJ2IjoiMjY1In0seyJuIjoi546w5a6e5bCP6K+0IiwidiI6IjI2NiJ9LHsibiI6IuS7meS+oOWlh+e8mCIsInYiOiIyNzYifSx7Im4iOiLku5nkvqDlpYflubsiLCJ2IjoiMjg4In0seyJuIjoi5q2m5L6g5bCP6K+0IiwidiI6IjI4OSJ9LHsibiI6IueOsOS7o+WGm+aXhSIsInYiOiIyOTAifV19XQogICAgfSwKICAgIGZpbHRlcl91cmw6ICJ7e2ZsLnR5cGV9fSIsCiAgICBmaWx0ZXJfZGVmOiB7fSwKICAgIGhlYWRlcnM6IHsnVXNlci1BZ2VudCc6ICdNb3ppbGxhLzUuMCAoV2luZG93cyBOVCAxMC4wOyBXaW42NDsgeDY0KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvMTM5LjAuMC4wIFNhZmFyaS81MzcuMzYnfSwKICAgIHNpZ25faGVhZGVyczogewogICAgICAgICJhcHAtdmVyc2lvbiI6ICI1MTExMCIsICJwbGF0Zm9ybSI6ICJhbmRyb2lkIiwgInJlZyI6ICIwIiwgIkFVVEhPUklaQVRJT04iOiAiIiwKICAgICAgICAiYXBwbGljYXRpb24taWQiOiAiY29tLioqKioucmVhZGVyIiwgIm5ldC1lbnYiOiAiMSIsICJjaGFubmVsIjogInVua25vd24iLCAicW0tcGFyYW1zIjogIiIKICAgIH0sCiAgICB0aW1lb3V0OiAxMDAwMCwKICAgIHBsYXlfcGFyc2U6IHRydWUsCgogICAgYXBpUmVxdWVzdDogYXN5bmMgZnVuY3Rpb24gKGVuZHBvaW50LCBwYXJhbXMgPSB7fSwgb3B0aW9ucyA9IHt9KSB7CiAgICAgICAgY29uc3QgaG9zdCA9IG9wdGlvbnMuaG9zdCB8fCB0aGlzLmhvc3Q7CiAgICAgICAgcGFyYW1zLmltZWlfaXAgPSBwYXJhbXMuaW1laV9pcCB8fCAnMjkzNzM1NzEwNyc7CiAgICAgICAgcGFyYW1zLnNpZ24gPSBnZXRTaWduU3RyKHBhcmFtcyk7CiAgICAgICAgY29uc3QgdXJsID0gYnVpbGRVcmwoYCR7aG9zdH0ke2VuZHBvaW50fWAsIHBhcmFtcyk7CiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnJlcXVlc3QodXJsLCB7CiAgICAgICAgICAgIGhlYWRlcnM6IG9wdGlvbnMuaGVhZGVycyB8fCB0aGlzLnNpZ25faGVhZGVycywKICAgICAgICAgICAgbWV0aG9kOiBvcHRpb25zLm1ldGhvZCB8fCAnR0VUJwogICAgICAgIH0pOwogICAgICAgIHJldHVybiBKU09OLnBhcnNlKHJlc3BvbnNlKTsKICAgIH0sCiAgICAKICAgIHJlcXVlc3Q6IGFzeW5jIGZ1bmN0aW9uICh1cmwsIG9iaikgewogICAgICAgIG9iaiA9IG9iaiB8fCB7fTsKICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IF9mZXRjaCh1cmwsIHsKICAgICAgICAgICAgbWV0aG9kOiBvYmoubWV0aG9kIHx8ICdHRVQnLAogICAgICAgICAgICBoZWFkZXJzOiBvYmouaGVhZGVycyB8fCB0aGlzLmhlYWRlcnMKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpOwogICAgfSwKCiAgICDpooTlpITnkIY6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICB0aGlzLnNpZ25faGVhZGVycy5zaWduID0gZ2V0U2lnblN0cih0aGlzLnNpZ25faGVhZGVycyk7CiAgICB9LAoKICAgIOS4gOe6pzogYXN5bmMgZnVuY3Rpb24gKHRpZCwgcGcsIGZpbHRlciwgZXh0ZW5kKSB7CiAgICAgICAgbGV0IGQgPSBbXTsKICAgICAgICBjb25zdCBjYXRlTWFwID0geycxJzonMjAyJywgJzInOicxJywgJzMnOicyNDAnfTsKICAgICAgICBjb25zdCB0eXBlSWQgPSB0aWQgIT09ICctMScgPyB0aWQgOiAnMic7CiAgICAgICAgbGV0IGNhdGVnb3J5X2lkID0gY2F0ZU1hcFt0eXBlSWRdIHx8ICcxJzsKICAgICAgICBjb25zdCB2YWxpZFN1YlR5cGVzU2V0ID0gbmV3IFNldCgpOwogICAgICAgIE9iamVjdC52YWx1ZXModGhpcy5maWx0ZXIpLmZvckVhY2goZmlsdGVyR3JvdXAgPT4gewogICAgICAgICAgICBmaWx0ZXJHcm91cC5mb3JFYWNoKGl0ZW0gPT4gewogICAgICAgICAgICAgICAgaXRlbS52YWx1ZS5mb3JFYWNoKHN1YlR5cGUgPT4gewogICAgICAgICAgICAgICAgICAgIHZhbGlkU3ViVHlwZXNTZXQuYWRkKHN1YlR5cGUudik7CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgICAgCiAgICAgICAgaWYgKGV4dGVuZD8udHlwZSAmJiB2YWxpZFN1YlR5cGVzU2V0LmhhcyhleHRlbmQudHlwZSkpIHsKICAgICAgICAgICAgY2F0ZWdvcnlfaWQgPSBleHRlbmQudHlwZTsKICAgICAgICB9IGVsc2UgaWYgKGZpbHRlciAmJiB2YWxpZFN1YlR5cGVzU2V0LmhhcyhmaWx0ZXIpKSB7CiAgICAgICAgICAgIGNhdGVnb3J5X2lkID0gZmlsdGVyOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBjb25zdCBwYXJhbXMgPSB7CiAgICAgICAgICAgIGdlbmRlcjogdHlwZUlkLAogICAgICAgICAgICBjYXRlZ29yeV9pZDogY2F0ZWdvcnlfaWQsCiAgICAgICAgICAgIG5lZWRfZmlsdGVyczogJzEnLAogICAgICAgICAgICBwYWdlOiBwZyB8fCAnMScsCiAgICAgICAgICAgIG5lZWRfY2F0ZWdvcnk6ICcxJwogICAgICAgIH07CiAgICAgICAgCiAgICAgICAgY29uc3QganNvbiA9IGF3YWl0IHRoaXMuYXBpUmVxdWVzdCgnL2FwaS92NC9jYXRlZ29yeS9nZXQtbGlzdCcsIHBhcmFtcyk7CiAgICAgICAgaWYgKGpzb24/LmRhdGE/LmJvb2tzKSB7CiAgICAgICAgICAgIGQgPSBqc29uLmRhdGEuYm9va3MubWFwKGl0ID0+ICh7CiAgICAgICAgICAgICAgICB0aXRsZTogaXQudGl0bGUsCiAgICAgICAgICAgICAgICB1cmw6IGAke3RoaXMuaG9zdH0vYXBpL3Y0L2Jvb2svZGV0YWlsP2lkPSR7aXQuaWR9YCwKICAgICAgICAgICAgICAgIGRlc2M6IGl0LmF1dGhvciwKICAgICAgICAgICAgICAgIHBpY191cmw6IGl0LmltYWdlX2xpbmssCiAgICAgICAgICAgICAgICBjb250ZW50OiBpdC5pbnRybwogICAgICAgICAgICB9KSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZXRSZXN1bHQoZCk7CiAgICB9LAoKICAgIOS6jOe6pzogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGxldCBWT0QgPSB7fTsKICAgICAgICBsZXQgYm9va0lkID0gdGhpcy5pbnB1dC5tYXRjaCgvaWQ9KFxkKykvKVsxXTsKICAgICAgICBjb25zdCBkZXRhaWxKc29uID0gYXdhaXQgdGhpcy5hcGlSZXF1ZXN0KCcvYXBpL3Y0L2Jvb2svZGV0YWlsJywgewogICAgICAgICAgICBpZDogYm9va0lkLAogICAgICAgICAgICB0ZWVueV9tb2RlOiAnMCcKICAgICAgICB9KTsKICAgICAgICBpZiAoZGV0YWlsSnNvbj8uZGF0YT8uYm9vaykgewogICAgICAgICAgICBsZXQgYm9vayA9IGRldGFpbEpzb24uZGF0YS5ib29rOwogICAgICAgICAgICBWT0QgPSB7CiAgICAgICAgICAgICAgICB2b2RfbmFtZTogYm9vay50aXRsZSwKICAgICAgICAgICAgICAgIHR5cGVfbmFtZTogYm9vay5ib29rX3RhZ19saXN0Py5tYXAodGFnID0+IHRhZy50aXRsZSkuam9pbignLCcpIHx8ICcnLAogICAgICAgICAgICAgICAgdm9kX3BpYzogYm9vay5pbWFnZV9saW5rLAogICAgICAgICAgICAgICAgdm9kX2NvbnRlbnQ6IGJvb2suaW50cm8sCiAgICAgICAgICAgICAgICB2b2RfcmVtYXJrczogYm9vay5sYXRlc3RfY2hhcHRlcl90aXRsZSwKICAgICAgICAgICAgICAgIHZvZF95ZWFyOiAnJywgdm9kX2FyZWE6ICcnLAogICAgICAgICAgICAgICAgdm9kX2FjdG9yOiBib29rLmF1dGhvciwgdm9kX2RpcmVjdG9yOiBib29rLmF1dGhvciwKICAgICAgICAgICAgICAgIHZvZF9wbGF5X2Zyb206ICfpmIXor7vliqnmiYsnCiAgICAgICAgICAgIH07CiAgICAgICAgICAgIGNvbnN0IHRvY0pzb24gPSBhd2FpdCB0aGlzLmFwaVJlcXVlc3QoJy9hcGkvdjEvY2hhcHRlci9jaGFwdGVyLWxpc3QnLCB7CiAgICAgICAgICAgICAgICBpZDogYm9vay5pZAogICAgICAgICAgICB9LCB7CiAgICAgICAgICAgICAgICBob3N0OiB0aGlzLmNoYXB0ZXJIb3N0CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBpZiAodG9jSnNvbj8uZGF0YT8uY2hhcHRlcl9saXN0cykgewogICAgICAgICAgICAgICAgVk9ELnZvZF9wbGF5X3VybCA9IHRvY0pzb24uZGF0YS5jaGFwdGVyX2xpc3RzLm1hcChjaGFwdGVyID0+IAogICAgICAgICAgICAgICAgICAgIGAke2NoYXB0ZXIudGl0bGV9JCR7Ym9vay5pZH1AQCR7Y2hhcHRlci5pZH1AQCR7Y2hhcHRlci50aXRsZX1gCiAgICAgICAgICAgICAgICApLmpvaW4oJyMnKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gVk9EOwogICAgfSwKCiAgICDmkJzntKI6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgZCA9IFtdOwogICAgICAgIGNvbnN0IGpzb24gPSBhd2FpdCB0aGlzLmFwaVJlcXVlc3QoJy9hcGkvdjUvc2VhcmNoL3dvcmRzJywgewogICAgICAgICAgICBnZW5kZXI6ICczJywKICAgICAgICAgICAgcGFnZTogdGhpcy5NWV9QQUdFLAogICAgICAgICAgICB3ZDogdGhpcy5LRVkKICAgICAgICB9KTsKICAgICAgICBpZiAoanNvbj8uZGF0YT8uYm9va3MpIHsKICAgICAgICAgICAgZCA9IGpzb24uZGF0YS5ib29rcy5tYXAoaXQgPT4gKHsKICAgICAgICAgICAgICAgIHRpdGxlOiBpdC5vcmlnaW5hbF90aXRsZSwKICAgICAgICAgICAgICAgIGRlc2M6IGl0LmF1dGhvciwKICAgICAgICAgICAgICAgIHBpY191cmw6IGl0LmltYWdlX2xpbmssCiAgICAgICAgICAgICAgICB1cmw6IGAke3RoaXMuaG9zdH0vYXBpL3Y0L2Jvb2svZGV0YWlsP2lkPSR7aXQuaWR9YCwKICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGl0LmludHJvCiAgICAgICAgICAgIH0pKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHNldFJlc3VsdChkKTsKICAgIH0sCgogICAgbGF6eTogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGxldCBbYm9va0lkLCBjaGFwdGVySWQsIHRpdGxlXSA9IHRoaXMuaW5wdXQuc3BsaXQoJ0BAJyk7CiAgICAgICAgbGV0IGNvbnRlbnQgPSAn5YaF5a655Yqg6L295aSx6LSlJzsKICAgICAgICBjb25zdCBqc29uID0gYXdhaXQgdGhpcy5hcGlSZXF1ZXN0KCcvYXBpL3YxL2NoYXB0ZXIvY29udGVudCcsIHsKICAgICAgICAgICAgaWQ6IGJvb2tJZCwKICAgICAgICAgICAgY2hhcHRlcklkCiAgICAgICAgfSwgewogICAgICAgICAgICBob3N0OiB0aGlzLmNoYXB0ZXJIb3N0CiAgICAgICAgfSk7CiAgICAgICAgaWYgKGpzb24/LmRhdGE/LmNvbnRlbnQpIGNvbnRlbnQgPSBkZWNvZGVDb250ZW50KGpzb24uZGF0YS5jb250ZW50KTsKICAgICAgICByZXR1cm4gewogICAgICAgICAgICBwYXJzZTogMCwKICAgICAgICAgICAgdXJsOiBgbm92ZWw6Ly8ke0pTT04uc3RyaW5naWZ5KHt0aXRsZSwgY29udGVudH0pfWAsCiAgICAgICAgICAgIGpzOiAnJwogICAgICAgIH07CiAgICB9Cn07CgpmdW5jdGlvbiBnZXRTaWduU3RyKHBhcmFtcykgewogICAgY29uc3Qgc2lnbl9rZXkgPSAiZDNkR2lKYzY1MWdTUTh3MSI7CiAgICByZXR1cm4gbWQ1KE9iamVjdC5rZXlzKHBhcmFtcykuc29ydCgpLnJlZHVjZSgocHJlLCBuKSA9PiBwcmUgKyBuICsgIj0iICsgcGFyYW1zW25dLCAiIikgKyBzaWduX2tleSk7Cn0KCmZ1bmN0aW9uIGRlY29kZUNvbnRlbnQoY29udGVudCkgewogICAgbGV0IGtleSA9IENyeXB0b0pTLmVuYy5VdGY4LnBhcnNlKCIyNDJjY2I4MjMwZDcwOWUxIik7CiAgICBsZXQgaXZFbmNEYXRhID0gQ3J5cHRvSlMuZW5jLkJhc2U2NC5wYXJzZShjb250ZW50KTsKICAgIGxldCBpdiA9IENyeXB0b0pTLmxpYi5Xb3JkQXJyYXkuY3JlYXRlKGl2RW5jRGF0YS53b3Jkcy5zbGljZSgwLCA0KSk7CiAgICBsZXQgZW5jcnlwdGVkID0gQ3J5cHRvSlMubGliLldvcmRBcnJheS5jcmVhdGUoaXZFbmNEYXRhLndvcmRzLnNsaWNlKDQpKTsKICAgIGxldCBkZWNyeXB0ZWQgPSBDcnlwdG9KUy5BRVMuZGVjcnlwdCh7Y2lwaGVydGV4dDogZW5jcnlwdGVkfSwga2V5LCB7CiAgICAgICAgaXYsIG1vZGU6IENyeXB0b0pTLm1vZGUuQ0JDLCBwYWRkaW5nOiBDcnlwdG9KUy5wYWQuUGtjczcKICAgIH0pOwogICAgcmV0dXJuIGRlY3J5cHRlZC50b1N0cmluZyhDcnlwdG9KUy5lbmMuVXRmOCk7Cn0= \ No newline at end of file From f29420d8310ba990173290e3d6bde4657af2948c Mon Sep 17 00:00:00 2001 From: Taois Date: Fri, 16 Jan 2026 10:58:19 +0800 Subject: [PATCH 029/101] fix:some source --- ...\346\274\253\347\224\273[\347\224\273].js" | 252 ++++++++++++++++++ ...\346\274\253\347\224\273[\347\224\273].js" | 68 +++-- ...\345\212\251\346\211\213[\344\271\246].js" | 12 + 3 files changed, 305 insertions(+), 27 deletions(-) create mode 100644 "spider/catvod/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" diff --git "a/spider/catvod/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" "b/spider/catvod/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" new file mode 100644 index 00000000..1afdc504 --- /dev/null +++ "b/spider/catvod/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" @@ -0,0 +1,252 @@ +/* +@header({ + searchable: 1, + filterable: 0, + quickSearch: 0, + title: '番茄漫画', + '类型': '漫画', + lang: 'ds' +}) +*/ +import cheerio from 'assets://js/lib/cheerio.min.js'; + +let HOST = 'https://qkfqapi.vv9v.cn'; +let UA = { + "User-Agent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36" +}; + +async function request(url, obj) { + if (!obj) { + obj = { + headers: UA, + timeout: 5000 + } + } + const response = await req(url, obj); + return response.content; +} + +function init(cfg) { + const ext = cfg.ext; + console.log('番茄漫画源初始化'); + console.log('初始化完成'); +} + +async function home(filter) { + try { + let html = await request('https://qkfqapi.vv9v.cn/api/discover/style?tab=漫画&source_type=男频'); + let json = JSON.parse(html); + let data = json.data; + let d = []; + data.forEach((it) => { + if (it.url && it.url.trim() !== '') { + d.push({ + type_name: it.title, + type_id: it.url, + }); + } + }); + return JSON.stringify({ + 'class': d + }); + } catch (error) { + console.log('home函数错误:', error); + } +} + + +async function homeVod(params) { + try { + let url = HOST + '/api/discover?tab=漫画&type=7&gender=2&genre_type=110&page=1'; + let html = await request(url); + let json = JSON.parse(html); + + if (json && json.data) { + let data = json.data.data || json.data; + let d = []; + + data.forEach((item) => { + if (item && item.book_name) { + d.push({ + vod_name: item.book_name, + vod_id: item.book_id || item.id, + vod_pic: item.thumb_url || item.cover, + vod_remarks: item.author || item.category || '', + vod_content: item.abstract || item.description || '' + }); + } + }); + + return JSON.stringify({ + list: d + }); + } + } catch (error) { + console.log('首页推荐请求错误:', error); + } +} + +async function category(tid, pg, filter, extend) { + try { + let url = tid; + let html = await request(url); + let json = JSON.parse(html); + + if (json && json.data) { + let data = json.data.data || json.data; + let d = []; + + data.forEach((item) => { + if (item && item.book_name) { + d.push({ + vod_name: item.book_name, + vod_id: item.book_id || item.id, + vod_pic: item.thumb_url || item.cover, + vod_remarks: item.author || item.category || '', + vod_content: item.abstract || item.description || '' + }); + } + }); + + if (d.length > 0) { + return JSON.stringify({ + list: d, + page: pg, + pagecount: 999, + limit: 20, + total: 999 + }); + } + } + } catch (error) { + console.log('分类请求错误:', error); + } +} + +async function detail(vod_url) { + try { + let detailUrl = HOST + '/api/detail?book_id=' + vod_url; + let json = JSON.parse(await request(detailUrl)); + + if (json?.data?.data) { + let data = json.data.data; + let vod = { + vod_name: data.book_name || '', + vod_id: vod_url, + type_name: data.category || '', + vod_pic: data.thumb_url || '', + vod_content: data.abstract || '', + vod_remarks: data.sub_info || '', + vod_director: data.author || '', + vod_play_from: '番茄漫画', + vod_play_url: '' + }; + + let chapterUrl = HOST + '/api/book?book_id=' + vod_url; + let chapterJson = JSON.parse(await request(chapterUrl)); + if (chapterJson?.data?.data) { + let bookInfo = chapterJson.data.data; + let list = bookInfo.chapterListWithVolume.flat(); + + let urls = []; + list.forEach((it) => { + if (it && it.title && it.itemId) { + urls.push(it.title + '$' + it.itemId + '@' + it.title); + } + }); + vod.vod_play_url = urls.join('#'); + } + + return JSON.stringify({list: [vod]}); + } + } catch (error) { + console.log('详情请求错误:', error); + } +} + +async function play(flag, id, flags) { + try { + let itemId = id; + let title = ''; + + if (id.includes('@')) { + let parts = id.split('@'); + itemId = parts[0]; + title = parts[1] || ''; + } + + let url = HOST + '/api/content?tab=漫画&item_id=' + itemId + '&show_html=0'; + let html = await request(url); + let json = JSON.parse(html); + let images = json.data.images; + images = pdfa(images, 'img'); + let pics = []; + images.forEach((img) => { + let pic = pdfh(img, 'img&&src'); + pics.push(pic); + }); + + if (pics.length > 0) { + return JSON.stringify({ + parse: 0, + url: 'pics://' + pics.join('&&') + }); + } + } catch (error) { + console.log('播放 请求错误:', error); + } +} + +async function search(wd, quick) { + try { + let searchUrl = HOST + '/api/search?key=' + encodeURIComponent(wd) + '&tab_type=8&offset=0'; + let html = await request(searchUrl); + let json = JSON.parse(html); + + if (json && json.data) { + let searchTabs = json.data.search_tabs || []; + let bookList = []; + + if (searchTabs.length > 3 && searchTabs[3].data) { + bookList = searchTabs[3].data; + } else if (json.data.data) { + bookList = json.data.data; + } + + let d = []; + bookList.forEach((item) => { + let book = item.book_data ? item.book_data[0] : item; + if (book && book.book_name) { + d.push({ + vod_name: book.book_name, + vod_id: book.book_id, + vod_pic: book.thumb_url || '', + vod_remarks: book.author || '', + vod_content: book.book_abstract || book.abstract || '' + }); + } + }); + + return JSON.stringify({ + list: d + }); + } + } catch (error) { + console.log('搜索请求错误:', error); + } +} + +function proxy(params) { + return [200, 'text/plain;charset=utf-8', '番茄漫画源代理测试', null]; +} + +export default { + init: init, + home: home, + homeVod: homeVod, + category: category, + detail: detail, + play: play, + search: search, + proxy: proxy, +} \ No newline at end of file diff --git "a/spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" "b/spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" index 230432e8..04519808 100644 --- "a/spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" +++ "b/spider/js/\347\225\252\350\214\204\346\274\253\347\224\273[\347\224\273].js" @@ -13,7 +13,8 @@ var rule = { 类型: '漫画', title: '番茄漫画', host: 'https://qkfqapi.vv9v.cn', - url: '', + homeUrl: '/api/discover/style?tab=漫画', + url: 'fyclass', searchUrl: '/api/search?key=**&tab_type=8&offset=((fypage-1)*10)', detailUrl: '/api/detail?book_id=fyid', headers: {'User-Agent': 'UC_UA'}, @@ -22,11 +23,19 @@ var rule = { filterable: 0, double: true, play_parse: true, - limit: 12, - // class_parse: async function () { - // let {input, pdfa, pdfh, pd} = this; - // return {} - // }, + limit: 10, + class_parse: async function () { + let {input} = this; + let html = await request(input); + let data = html.parseX.data; + let d = data.filter(item => item.url.trim()).map((it) => { + return { + type_name: it.title, + type_id: it.url, + } + }); + return {class: d} + }, lazy: async function () { let {input, pdfa, pdfh} = this; let title = input.split('@')[1]; @@ -42,24 +51,38 @@ var rule = { } return {parse: 0, url: 'pics://' + pics.join('&&')} }, + parseList(html) { + let data = html.parseX.data; + data = data.data || data; + let d = []; + data.forEach((item) => { + if (item && item.book_name) { + d.push({ + vod_name: item.book_name, + vod_id: item.book_id || item.id, + vod_pic: item.thumb_url || item.cover, + vod_remarks: item.author || item.category || '', + vod_content: item.abstract || item.description || '' + }); + } + }); + return d + }, 推荐: async function () { - return [{ - vod_id: 'only_search', - vod_name: '纯搜索源哦!', - vod_tag: 'action', - vod_pic: this.publicUrl + '/images/icon_cookie/搜索.jpg' - }]; + let {HOST} = this; + let url = HOST + '/api/discover?tab=漫画&type=7&gender=2&genre_type=110&page=1'; + let html = await request(url); + return this.parseList(html); }, - 一级: async function () { - return []; + 一级: async function (tid, pg, filter, extend) { + input = jinja.render(tid, {page: pg}); + let html = await request(input); + return this.parseList(html); }, 二级: async function () { let {input, orId} = this; - // log('input', input); - // log('orId', orId); let html = await request(input); - let json = JSON.parse(html); - let data = json.data.data; + let data = html.parseX.data.data; let VOD = {}; VOD.vod_name = data.book_name; VOD.type_name = data.category; @@ -83,10 +106,6 @@ var rule = { }, 搜索: async function () { let {input, MY_PAGE} = this; - // if (Number(MY_PAGE) > 1) { - // return [] - // } - print(input) let html = await request(input); let json = JSON.parse(html); let data = json.data.search_tabs[3].data; @@ -104,9 +123,4 @@ var rule = { } return setResult(d) }, - action: async function (action, value) { - if (action === 'only_search') { - return '此源为纯搜索源,你直接全局搜索这个源或者使用此页面的源内搜索就好了' - } - } } \ No newline at end of file diff --git "a/spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" "b/spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" index 40f61d11..fed18169 100644 --- "a/spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" +++ "b/spider/js/\351\230\205\350\257\273\345\212\251\346\211\213[\344\271\246].js" @@ -1,3 +1,15 @@ +/* +@header({ + searchable: 2, + filterable: 1, + quickSearch: 0, + title: '阅读助手[书]', + author: 'EylinSir', + '类型': '小说', + lang: 'ds' +}) +*/ + var rule = { 类型: '小说', author: 'EylinSir', From 566e6abfd343d1a4a799bde1cab3ba45daa54db4 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Fri, 16 Jan 2026 21:02:36 +0800 Subject: [PATCH 030/101] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8E=BB=E8=AF=BB?= =?UTF-8?q?=E4=B9=A6[=E4=B9=A6].js=E6=96=87=E4=BB=B6=E7=9A=84=E6=AD=A3?= =?UTF-8?q?=E5=88=99=E6=9B=BF=E6=8D=A2=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\350\257\273\344\271\246[\344\271\246].js" | 139 ++++++++---------- 1 file changed, 60 insertions(+), 79 deletions(-) diff --git "a/spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" "b/spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" index 86b8b485..44b8f662 100644 --- "a/spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" +++ "b/spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" @@ -29,38 +29,23 @@ var rule = { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36' }, - request: async function (url, obj) { - obj = obj || {}; - try { - const response = await _fetch(url, { - method: obj.method || 'GET', - headers: obj.headers || this.headers - }); - return response.text(); - } catch (err) { - return ''; - } - }, - + 一级: async function () { let {input, pdfa, pdfh, pd} = this; - let url = input.startsWith('http') ? input : this.host + '/book/' + input + '/0/1.html'; - let html = await this.request(url); + let url = input.startsWith('http') ? input : `${this.host}/book/${input}/0/1.html`; + let html = await request(url); let d = []; let items = pdfa(html, '.blockcontent .c_row') || pdfa(html, '.c_row') || []; for (let item of items) { let title = pdfh(item, '.c_subject a:eq(1)&&Text'); - let itemUrl = pd(item, '.c_subject a:eq(1)&&href'); - if (!title || !itemUrl) continue; - let remarks = pdfh(item, '.c_tag span:eq(1)&&Text') || ''; - let pic = pd(item, 'img&&src') || ''; - let content = pdfh(item, '.c_description&&Text') || ''; + let url = pd(item, '.c_subject a:eq(1)&&href'); + if (!title || !url) continue; d.push({ - title: title, - url: itemUrl, - desc: remarks, - pic_url: pic, - content: content, + title, + url, + desc: pdfh(item, '.c_tag span:eq(1)&&Text') || '', + pic_url: pd(item, 'img&&src') || '', + content: pdfh(item, '.c_description&&Text') || '', }); } return setResult(d); @@ -68,58 +53,52 @@ var rule = { 二级: async function () { let {input, pdfa, pdfh, pd} = this; - let html = await this.request(input); - let VOD = {}; - VOD.vod_name = pdfh(html, '[property="og:novel:book_name"]&&content') || ''; - VOD.type_name = ''; - VOD.vod_pic = pd(html, '.divbox.cf img&&src') || ''; - VOD.vod_content = pdfh(html, '.tabcontent .tabvalue:eq(0)&&Text') || ''; - VOD.vod_remarks = pdfh(html, 'h3 a&&Text') || ''; - VOD.vod_year = ''; - VOD.vod_area = ''; - VOD.vod_actor = pdfh(html, '[property="og:novel:author"]&&content') || ''; - VOD.vod_director = VOD.vod_actor; - VOD.vod_play_from = '去读书网'; - let toc_url = pd(html, 'a:contains(点击阅读)&&href') || ''; - if (toc_url && !toc_url.startsWith('http')) { - toc_url = this.host + toc_url; - } - let toc_html = toc_url ? await this.request(toc_url) : ''; + let html = await request(input); + let VOD = { + vod_name: pdfh(html, '[property="og:novel:book_name"]&&content') || '', + type_name: '', + vod_pic: pd(html, '.divbox.cf img&&src') || '', + vod_content: pdfh(html, '.tabcontent .tabvalue:eq(0)&&Text') || '', + vod_remarks: pdfh(html, 'h3 a&&Text') || '', + vod_year: '', + vod_area: '', + vod_actor: pdfh(html, '[property="og:novel:author"]&&content') || '', + vod_director: '', + vod_play_from: '去读书网', + vod_play_url: '' + }; + VOD.vod_director = VOD.vod_actor; // 复用作者信息 + let tocUrl = pd(html, 'a:contains(点击阅读)&&href') || ''; + tocUrl = tocUrl && !tocUrl.startsWith('http') ? `${this.host}${tocUrl}` : tocUrl; + let tocHtml = tocUrl ? await request(tocUrl) : ''; let chapters = []; - let chapterItems = pdfa(toc_html, '.index li') || []; - for (let chapter of chapterItems) { - let title = pdfh(chapter, 'a&&Text'); - let chapter_url = pd(chapter, 'a&&href'); - if (!title || !chapter_url) continue; - if (!chapter_url.startsWith('http')) { - chapter_url = this.host + chapter_url; - } - chapters.push(title + '$' + chapter_url); + let chs = pdfa(tocHtml, '.index li') || []; + for (let ch of chs) { + let title = pdfh(ch, 'a&&Text'); + let chUrl = pd(ch, 'a&&href'); + if (!title || !chUrl) continue; + chUrl = chUrl.startsWith('http') ? chUrl : `${this.host}${chUrl}`; + chapters.push(`${title}$${chUrl}`); } VOD.vod_play_url = chapters.join('#'); return VOD; }, 搜索: async function () { - let {KEY, pdfa, pdfh, pd} = this; - let url = this.host + this.searchUrl.replace('**', encodeURIComponent(KEY)); - let html = await this.request(url); - if (!html) { - url = this.host + '/modules/article/search.php?q=' + encodeURIComponent(KEY); - html = await this.request(url); - } + let {input, pdfa, pdfh, pd} = this; + let html = await request(input); let d = []; let items = pdfa(html, '#jieqi_page_contents .c_row') || []; for (let item of items) { let title = pdfh(item, '.c_subject a&&Text'); - let itemUrl = pd(item, '.c_subject a&&href'); - if (!title || !itemUrl) continue; - itemUrl = itemUrl.startsWith('http') ? itemUrl : this.host + itemUrl; + let url = pd(item, '.c_subject a&&href'); + if (!title || !url) continue; + url = url.startsWith('http') ? url : `${this.host}${url}`; let pic = pd(item, 'img&&src') || ''; - pic = pic.startsWith('http') ? pic : this.host + pic; + pic = pic.startsWith('http') ? pic : `${this.host}${pic}`; d.push({ - title: title, - url: itemUrl, + title, + url, desc: pdfh(item, '.c_tag span:eq(1)&&Text') || '', pic_url: pic, content: '', @@ -127,29 +106,31 @@ var rule = { } return setResult(d); }, - + // 懒加载解析(章节内容) lazy: async function () { let {input, pdfh} = this; - let html = await this.request(input); + let html = await request(input); let title = pdfh(html, 'h1&&Text') || ''; let content = pdfh(html, '#acontent&&Html') || ''; if (content) { - content = content.replace(/]*?>.*?<\/script>/gs, '') - .replace(/<\/p>/g, '\n\n') - .replace(/]*?>/g, '\n') - .replace(/<[^>]*?>/g, '') - .replace(/去读书推荐各位书友阅读:.*|去读书 www\.qudushu\.la|如果您中途有事离开,请按.*以便以后接着观看!/g, '') - .replace(/[()]/g, '') - .replace(/ /g, ' ') - .replace(/[ \t]+/g, ' ') - .replace(/\n[ \t]+|[ \t]+\n/g, '\n') - .replace(/\n+/g, '\n\n') - .trim(); + const replaceRules = [ + [/]*?>[\s\S]*?<\/script>/gi, ''], + [/<\/p>|/g, '\n'], + [/<[^>]*?>/g, ''], + [/去读书推荐各位书友阅读:.*|去读书 www\.qudushu\.la|如果您中途有事离开,请按.*以便以后接着观看!/g, ''], + [/ |[ \t]+/g, ' '], + [/\n[ \t]*\n+/g, '\n'] + ]; + replaceRules.forEach(([reg, val]) => content = content.replace(reg, val)); + content = content.trim(); + if (content.startsWith(title)) { + content = content.replace(title, '').trim(); + } } return { parse: 0, - url: 'novel://' + JSON.stringify({title, content}), + url: `novel://${JSON.stringify({title, content})}`, js: '' }; } -}; +}; \ No newline at end of file From 7689b51afe0936a6f9f193dc0359cefb233fe366 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Fri, 16 Jan 2026 21:04:24 +0800 Subject: [PATCH 031/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0jx/web1.js=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=9A=84URL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jx/web1.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jx/web1.js b/jx/web1.js index e190d820..6c870d83 100644 --- a/jx/web1.js +++ b/jx/web1.js @@ -63,7 +63,7 @@ const jx = { * 添加url属性直接暴露api,不走系统。建议web解析才写这个属性,json解析隐藏起来 * @type {string} */ - url: 'https://bfq.cfwlgzs.cn/player?url=', + url: 'https://www.ckplayer.vip/jiexi/?url=', }; /** From ba268e539b089c8a0a29210f55c92b78c5be88e6 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Fri, 16 Jan 2026 22:48:49 +0800 Subject: [PATCH 032/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=8A=AA=E5=8A=AA?= =?UTF-8?q?=E4=B9=A6=E5=9D=8A[=E4=B9=A6].js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...16\273\350\257\273\344\271\246[\344\271\246].js" | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git "a/spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" "b/spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" index 44b8f662..7a0c87f6 100644 --- "a/spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" +++ "b/spider/js/\345\216\273\350\257\273\344\271\246[\344\271\246].js" @@ -26,9 +26,7 @@ var rule = { filterable: 0, timeout: 10000, play_parse: true, - headers: { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36' - }, + headers: { 'User-Agent': 'MOBILE_UA' }, 一级: async function () { let {input, pdfa, pdfh, pd} = this; @@ -56,16 +54,11 @@ var rule = { let html = await request(input); let VOD = { vod_name: pdfh(html, '[property="og:novel:book_name"]&&content') || '', - type_name: '', vod_pic: pd(html, '.divbox.cf img&&src') || '', vod_content: pdfh(html, '.tabcontent .tabvalue:eq(0)&&Text') || '', vod_remarks: pdfh(html, 'h3 a&&Text') || '', - vod_year: '', - vod_area: '', vod_actor: pdfh(html, '[property="og:novel:author"]&&content') || '', - vod_director: '', - vod_play_from: '去读书网', - vod_play_url: '' + vod_play_from: '去读书网' }; VOD.vod_director = VOD.vod_actor; // 复用作者信息 let tocUrl = pd(html, 'a:contains(点击阅读)&&href') || ''; @@ -106,7 +99,7 @@ var rule = { } return setResult(d); }, - // 懒加载解析(章节内容) + lazy: async function () { let {input, pdfh} = this; let html = await request(input); From 435e9137c356a2200ff17966dbf714c803dfeffb Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Fri, 16 Jan 2026 23:00:43 +0800 Subject: [PATCH 033/101] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B9=90=E4=B9=90?= =?UTF-8?q?=E4=B9=A6=E6=88=BF[=E4=B9=A6].js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\344\271\246\345\235\212[\344\271\246].js" | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 "spider/js/\345\212\252\345\212\252\344\271\246\345\235\212[\344\271\246].js" diff --git "a/spider/js/\345\212\252\345\212\252\344\271\246\345\235\212[\344\271\246].js" "b/spider/js/\345\212\252\345\212\252\344\271\246\345\235\212[\344\271\246].js" new file mode 100644 index 00000000..55c284fd --- /dev/null +++ "b/spider/js/\345\212\252\345\212\252\344\271\246\345\235\212[\344\271\246].js" @@ -0,0 +1,136 @@ +/* +@header({ + searchable: 1, + filterable: 0, + quickSearch: 1, + title: '努努书坊[书]', + author: 'EylinSir', + '类型': '小说', + logo: 'https://www.nunubook.com/favicon.ico', + lang: 'ds' +}) +*/ + +var rule = { + 类型: '小说', + author: 'EylinSir', + title: '努努书坊[书]', + host: 'https://www.nunubook.com', + url: '/fyclass/##fypage', + logo: 'https://www.nunubook.com/favicon.ico', + class_name: '玄幻小说&魔幻小说&悬疑小说&历史架空&都市小说&言情小说&武侠小说&官场小说&现代小说&战争军事&侦探推理&外国小说&纪实小说&诗歌戏曲&宗教哲学&文学理论&寓言童话&科普学习&社会心理&作品集&传记回忆&杂文随笔', + class_url: 'xuanhuan&mohuan&xuanyi&lishi&dushi&yanqing&wuxia&guanchang&xiandaixiaoshuo&zhanzhengjunshi&zhentantuili&waiguo&jishi&shigexiqu&zhexue&wenxuelilun&yuyantonghua&kepuxuexi&shehuixinli&zuopinji&zhuanjihuiyi&zawen', + searchUrl: '/e/search/index.php?tbname=bookname&show=title&tempid=1&keyboard=**', + searchable: 1, + quickSearch: 1, + filterable: 0, + timeout: 10000, + play_parse: true, + headers: { 'User-Agent': 'MOBILE_UA' }, + + 一级: async function () { + let [cateUrl, pg] = this.input.split('##'); + let list = []; + let cateKey = cateUrl.split('/').filter(Boolean).pop() || ''; + let cl = this.class_url.split('&').findIndex(k => k === cateKey) + 1 || undefined; + if (pg === '1') { + let html = await request(cateUrl); + let selectors = ['.listBig-li', 'li.listBig-li', '.book-item', '.list-item']; + let items = selectors.map(sel => this.pdfa(html, sel)).find(Boolean); + items?.forEach(item => { + let urlSelectors = ['a:eq(0)&&href', 'a&&href']; + let url = urlSelectors.map(sel => this.pd(item, sel)).find(Boolean) || this.pdfh(item, 'a&&href'); + if (url) { + url = url.startsWith('http') ? url : `${this.host}${url}`; + let title = this.pdfh(item, 'h3&&Text') || this.pdfh(item, 'h2&&Text') || '未知标题'; + let desc = this.pdfh(item, 'p:eq(0)&&Text') || '无简介'; + list.push({ + title, + url, + desc, + pic_url: this.pd(item, 'img&&src') || '', + content: this.pdfh(item, '.text&&Text') || desc + }); + } + }); + } else if (cl) { + let apiUrl = `${this.host}/e/extend/more/lsmore.php?page=${pg}&line=10&cl=${cl}`; + let json = JSON.parse(await request(apiUrl)); + list.push(...json.map(item => ({ + title: item.title, + url: item.url, + pic_url: item.pic, + desc: item.smalltext, + content: `${item.smalltext}\n作者:${item.writer}` + }))); + } + return setResult(list); + }, + + 二级: async function () { + let html = await request(this.input); + let VOD = { + vod_name: this.pdfh(html, 'h1&&Text'), + vod_pic: this.pdfh(html, '[property$=image]&&content'), + vod_content: this.pdfh(html, '[property$=description]&&content'), + vod_actor: this.pdfh(html, '[property$=author]&&content') + }; + let id = this.input.match(/\/(\d+)(\/|\.html)/)?.[1]; + if (id) { + let baseUrl = `${this.host}/e/extend/bookpage/pages.php?id=${id}&dz=asc&pageNum=`; + let firstPage = JSON.parse(await request(baseUrl + '0')); + let chapters = firstPage.list || []; + if (firstPage.totalPage > 0) { + let reqs = []; + for (let i = 1; i <= firstPage.totalPage; i++) reqs.push(request(baseUrl + i)); + let res = await Promise.all(reqs); + res.forEach(r => { chapters = chapters.concat(JSON.parse(r).list || []) }); + } + VOD.vod_play_from = '努努书坊'; + VOD.vod_play_url = chapters.map(c => { + let url = c.pic || c.url; + return c.title + '$' + (url.startsWith('http') ? url : `${this.host}${url}`); + }).join('#'); + } + return VOD; + }, + + 搜索: async function () { + let [url, params] = this.input.split('?'); + let html = await post(url, { body: params }); + let list = []; + if (!html.includes('没有搜索到')) { + (this.pdfa(html, '.search-wrap-first') || []).forEach(item => { + let url = this.pd(item, 'a&&href'); + if (url) list.push({ + title: this.pdfh(item, 'h3&&Text').replace('小说', ''), + url: url.startsWith('http') ? url : `${this.host}${url}`, + pic_url: this.pd(item, 'img&&src'), + content: this.pdfh(item, 'p&&Text') + }); + }); + } + return setResult(list); + }, + + lazy: async function () { + let { input, pdfh } = this; + let html = await request(input); + let content = pdfh(html, '#text&&Html') || ''; + if (content) { + content = content + .replace(/]*?>.*?<\/script>/gs, '') + .replace(/<\/p>/g, '\n\n') + .replace(//gi, '\n') + .replace(/<[^>]+>/g, '') + .replace(/ /g, ' ') + .replace(/\n\s*\n/g, '\n\n') + .trim(); + } + return { + parse: 0, + url: `novel://${JSON.stringify({ title: pdfh(html, 'h1&&Text') || '', content })}`, + js: '' + }; + } +}; \ No newline at end of file From ba9255e28306b965d71cf81caa7cbf5b37f14d24 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Sat, 17 Jan 2026 10:05:17 +0800 Subject: [PATCH 034/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=A4=9A=E4=B8=AA?= =?UTF-8?q?=E6=96=87=E4=BB=B6=EF=BC=9A=E4=BF=AE=E6=94=B9JSON=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E7=9B=B8=E5=85=B3=E6=96=87=E4=BB=B6=EF=BC=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E8=85=BE=E8=AE=AF=E8=A7=86=E9=A2=91=EF=BC=8C=E9=87=8D?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E8=85=BE=E8=AE=AF=E5=8A=A8=E6=BC=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "jx/JSON\345\220\210\351\233\206.js" | 2 +- jx/json1.js | 2 +- ...\347\225\205\345\220\254[\345\220\254].js" | 101 ++++++++++++++++++ ...\347\237\255\345\211\247[\347\237\255].js" | 0 4 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 "spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" rename "spider/js/\347\225\252\350\214\204\347\237\255\345\211\247.js" => "spider/js/\347\225\252\350\214\204\347\237\255\345\211\247[\347\237\255].js" (100%) diff --git "a/jx/JSON\345\220\210\351\233\206.js" "b/jx/JSON\345\220\210\351\233\206.js" index b0f4703d..1965a65e 100644 --- "a/jx/JSON\345\220\210\351\233\206.js" +++ "b/jx/JSON\345\220\210\351\233\206.js" @@ -64,7 +64,7 @@ async function lazy(input, params) { * 包含多个备用解析接口,提高解析成功率 */ let parse_list = [ - "https://zy.qiaoji8.com/gouzi.php?url=", // 主要解析接口 + "https://kalbim.xatut.top/kalbim2025/781718/play/video_player.php?url=", // 主要解析接口 "http://1.94.221.189:88/algorithm.php?url=" // 备用解析接口 ] diff --git a/jx/json1.js b/jx/json1.js index a588aa42..7a0886d5 100644 --- a/jx/json1.js +++ b/jx/json1.js @@ -82,7 +82,7 @@ async function lazy(input, params) { let timeout = 8000; // 设置请求超时时间为8秒 // 调用第三方解析API获取视频直链 - let obj = await requestJson('https://cdnsrc.cdnapi.top/json/?url=' + input, {headers, timeout}); + let obj = await requestJson('https://kalbim.xatut.top/kalbim2025/781718/play/video_player.php?url=' + input, {headers, timeout}); return obj.url // 返回解析后的视频播放链接 } diff --git "a/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" "b/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" new file mode 100644 index 00000000..b52c650c --- /dev/null +++ "b/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" @@ -0,0 +1,101 @@ +/* +@header({ + searchable: 1, + filterable: 0, + quickSearch: 0, + title: '番茄听书', + author: 'EylinSir', + '类型': '听书', + lang: 'ds' +}) +*/ + +var rule = { + 类型: '听书', + author: 'EylinSir', + title: '番茄听书', + host: 'https://qkfqapi.vv9v.cn', + url: '', + searchUrl: '/api/search?key=**&tab_type=2&offset=((fypage-1)*10)', + detailUrl: '/api/detail?book_id=fyid', + headers: {'User-Agent': 'UC_UA'}, + searchable: 1, + quickSearch: 0, + filterable: 0, + double: true, + play_parse: true, + limit: 12, + + action: async function (action, value) { + if (action === 'only_search') { + return '此源为纯搜索源,你直接全局搜索这个源或者使用此页面的源内搜索就好了'; + } + }, + + 推荐: async function () { + return [{ + vod_id: 'only_search', + vod_name: '纯搜索源哦!', + vod_tag: 'action', + vod_pic: this.publicUrl + '/images/icon_cookie/搜索.jpg' + }]; + }, + + 一级: async function () { + return []; + }, + + 二级: async function () { + let detailApi = `${this.host}/api/detail?book_id=${this.orId}`; + let detailJson = await request(detailApi); + let detailData = JSON.parse(detailJson); + let data = detailData.data.data; + let chaptersApi = `${this.host}/api/book?book_id=${this.orId}`; + let chaptersJson = await request(chaptersApi); + let chaptersData = JSON.parse(chaptersJson); + let bookData = chaptersData.data.data; + let list = bookData.chapterListWithVolume?.flat() || bookData.chapterList || []; + let urls = list.map(it => it.title + '$' + it.itemId + '@' + it.title).join('#'); + return { + vod_id: this.orId, + vod_name: data.book_name, + type_name: data.category, + vod_pic: data.thumb_url || data.expand_thumb_url, + vod_content: data.abstract || data.book_abstract_v2, + vod_remarks: data.sub_info, + vod_director: data.author, + vod_play_from: '番茄听书', + vod_play_url: urls + }; + }, + + 搜索: async function () { + let {input, MY_PAGE} = this; + let html = await request(input); + let json = JSON.parse(html); + let data = json.data.search_tabs[4].data; + let d = []; + for (let it of data.filter(i => i.book_data)) { + let book = it.book_data[0]; + d.push({ + title: book.book_name, + url: book.book_id, + desc: book.author, + content: book.book_abstract || book.abstract, + pic_url: book.thumb_url + }); + } + return setResult(d); + }, + + lazy: async function () { + let {input} = this; + let parts = input.split('@'); + let itemId = parts[0]; + let toneId = '1'; + let content_url = `${this.host}/api/content?item_id=${itemId}&tab=听书&tone_id=${toneId}`; + let jsonStr = await request(content_url); + let data = JSON.parse(jsonStr); + return {parse: 0, url: data.data.content}; + } +} \ No newline at end of file diff --git "a/spider/js/\347\225\252\350\214\204\347\237\255\345\211\247.js" "b/spider/js/\347\225\252\350\214\204\347\237\255\345\211\247[\347\237\255].js" similarity index 100% rename from "spider/js/\347\225\252\350\214\204\347\237\255\345\211\247.js" rename to "spider/js/\347\225\252\350\214\204\347\237\255\345\211\247[\347\237\255].js" From df5ecacacfdb7f344c1e9fcb659852f4002b294e Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Sat, 17 Jan 2026 10:21:43 +0800 Subject: [PATCH 035/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=85=BE=E8=AE=AF?= =?UTF-8?q?=E8=A7=86=E9=A2=91[=E8=A7=86].js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...52\350\214\204\347\225\205\345\220\254[\345\220\254].js" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" "b/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" index b52c650c..a1f2929f 100644 --- "a/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" +++ "b/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" @@ -3,7 +3,7 @@ searchable: 1, filterable: 0, quickSearch: 0, - title: '番茄听书', + title: '番茄畅听', author: 'EylinSir', '类型': '听书', lang: 'ds' @@ -13,7 +13,7 @@ var rule = { 类型: '听书', author: 'EylinSir', - title: '番茄听书', + title: '番茄畅听', host: 'https://qkfqapi.vv9v.cn', url: '', searchUrl: '/api/search?key=**&tab_type=2&offset=((fypage-1)*10)', @@ -64,7 +64,7 @@ var rule = { vod_content: data.abstract || data.book_abstract_v2, vod_remarks: data.sub_info, vod_director: data.author, - vod_play_from: '番茄听书', + vod_play_from: '番茄畅听', vod_play_url: urls }; }, From 5ad29727719972c9f81d8385901ddad3e85f2b11 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Sat, 17 Jan 2026 10:26:09 +0800 Subject: [PATCH 036/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=B9=A6=E6=BA=90?= =?UTF-8?q?=E9=85=8D=E7=BD=AE[=E7=AE=A1].js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\207\347\217\215\345\274\202\345\205\275[\345\256\230].js" | 4 ++++ 1 file changed, 4 insertions(+) diff --git "a/spider/js/\345\245\207\347\217\215\345\274\202\345\205\275[\345\256\230].js" "b/spider/js/\345\245\207\347\217\215\345\274\202\345\205\275[\345\256\230].js" index e82ac317..1ac29a6a 100644 --- "a/spider/js/\345\245\207\347\217\215\345\274\202\345\205\275[\345\256\230].js" +++ "b/spider/js/\345\245\207\347\217\215\345\274\202\345\205\275[\345\256\230].js" @@ -195,4 +195,8 @@ var rule = { }); return setResult(d); }, + lazy: async function () { + let {input} = this; + return {jx: 1, url: input} + } } From 9b3fc0bd6a5b9e38be5e144ae4f4eb18c5124350 Mon Sep 17 00:00:00 2001 From: Taois Date: Sat, 17 Jan 2026 17:01:21 +0800 Subject: [PATCH 037/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=862=E4=B8=AA?= =?UTF-8?q?=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...345\220\210\347\237\255\345\211\247[B].js" | 2 +- ...\344\271\246\345\235\212[\344\271\246].js" | 136 ++++++++++++++++++ 2 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 "spider/js/\345\212\252\345\212\252\344\271\246\345\235\212[\344\271\246].js" diff --git "a/spider/catvod/\350\223\235\350\216\223\350\201\232\345\220\210\347\237\255\345\211\247[B].js" "b/spider/catvod/\350\223\235\350\216\223\350\201\232\345\220\210\347\237\255\345\211\247[B].js" index 3b24d738..a699e4e1 100644 --- "a/spider/catvod/\350\223\235\350\216\223\350\201\232\345\220\210\347\237\255\345\211\247[B].js" +++ "b/spider/catvod/\350\223\235\350\216\223\350\201\232\345\220\210\347\237\255\345\211\247[B].js" @@ -8,4 +8,4 @@ }) */ -435F35785E45BA969DB95FC07396BBF327C50F94B452155A10B2127EB2743F686695A42CC071322F2A3F2D1F5DF8371791ED1331D3FC196192B1F5779953C4F0A74B825A27808280AF58BCEA6F33B6E1ADAD9A4FEA22075DE973CA16897BDFEE04A404065A3A4A9DF5598F7AD6F7312B612AF89D455139A6E96EE884F1D8D0404461A7D04472C01F875989C600C5C9B312189C7E05A8D06DE4EFC9C90E9626A577255A1BA848653FC669B7AEBBB00F15779981DF268A9FB202B853C63846F9220895F15EAA14568EBCEE1BC2CE35FF12BBC093E81BC02C4B57C6141ADC72B847C36F28028FF2BCD60D3AA72F6795DECC1A76CB2FF432D4DD66B253EF88909FC10E1FBFF1E7FD00ECDDA622B307053DA10648F23A133ED170B473B3DFE288C0219232673E5F11538B54534E9ED45A296E064C3FBBB1FA78DBAD5B7C42B2C286502F73421F3F448DC33E402961487AE257935734D0E20A2CB8037B47F2305DCDC5CB61AB7433D63150AC02AC258753EFED9E078291139039A81DD9E4EFD846D881724AE1A51228CD2D9E9D6896A63FF00479B9EF00BBC912F38FC624364BE0A1EE50BAECA4BA62D36D460EB0B70E4706EB787C62BF92D5B24629918C85EB2F0F914E58CD6759D248008B7388192A731530CC6E5CCBFA6B2C183114F6B099D7843510E012C2F7E09FDBA63EBF14AF321B293282997D1FB2B2199D350ABB235C7D4D4C40FE29993F5CE496AD45A26DBCB47527CCCCCC993BD007D29228BE3D813AD2B133390A39586B974FFFC524A9BFC96F68F9F295CB88A795AD7AD149E8139BE057244B9C2EF569AA1515845D22DE3654BF6B6149AAEDACCB9AFAA0B08FFA8B4104D3A2237FDBF6AAC3A1276C577C37113F3F411A8F6DEB33C2AD78341E9E9DD342EAD3FDD9D5546AF9381E50890249AD2E699F4E974D8808F8858E9B441373032693DE29ED770A0B9A35788A7C37E73922A0757471BEF52B8C0FEDADA03BE09A2DE1D222B5A2E20F0E56CF834BE8C7057F539D73728DBBBB6D06C79583CD86BB80B370A8EB643112C8234CE533FA48408B3BAA71DA651E566CAAF893F51FFF2F278041CA7EE421A03E96178BA38D585B168B4DC1FBBB4DBC855C425F74BA510A6E150175881E51ECD535EDC6B2C7C817CD5934C26A3486ACDB6C9E685D03B552DDD2D8D6D55903FF892B68C39097F05F422C27032D7CEADE1142C13C778291061E4F6F933B4795AA6DDAF057D5F4209AFEC7043F6F13C4B447BE11A7188BC439DF94D7F409BD7FDCBB726E213E02E78212620FD11599686CAF57D191B822BF6A2C3E4D387A3CAE2CE8F415DA13D83809908A9C9EEDBD797F8A6A3E0DFCDEFEE108B54E0155DEFF67291E2A850332634B28A28A213B5F4BA18B5F8AA5F0DD11558F32FDD9E78D15F67B04B91894EA8EB4F6506D60506C48B638ADF3CFB651590EE5AE5D869DA166CD23B634AF9A19AF1E5B70935CF0508EBA0D8F7A0D2B8321F91A0DAF61B708743A6EB7522289561273504A2A24A67F4651DB0DCBD44CBB4A62B9648FB814BF7C6E08671C03C7E0D2B56AED7E04332DDBD804559236022A9A4B0AF9CB04DB49D43B590E50943E248F86DE7F43F3E865022D842AB51BC9B9ECA8E47DD8DAA0786F161C5B5EF3E8C41A809AEA96F6B185BDE4F8A41306BA471740E5A38F6DD320F612A1AC3F10A485485124952139A26D1B30E5C3CAEAFB462927D28404FF79BBF0FED9C0BFA41708900E89E36FF8BB460C3BE6D94EF67626126A6F1449FBBC136E67FC3239E5F3793FC9E235A441C7CD3DAC7CECB1CBD4080F12C4C975F053045DC2B333BCE3ED7880A8C604718BAB96C339C9273C2BE62663833A99178882E6BC0125ED14B99A0E55535C65011BBA82EF1D5750BCED03CD31A2EFC249575011F387529639EB74B70F888850A50FE9477684F9A4E81B780CBC943315A303C12F65565DE3B060E66C733E355C7907DDC8401EDF2075B0EAAA4BE8EB9755DD92D3F3282DEDC7CC2771E256C7B1FC8434F2737D4C9C7A55072E36B8D9C07530E5FFBC2D70E643F0D3172D5BDAABF92B21DE2AF93966AE9D88EA917939B96D0A55351FD08BE8A07102196D87AEA586652BC53DBBC9952067D8E9E88AE6D12B772FF10057EB2BE32F2020B0E63AF8AD992F4696141353568FF720E3901980B27F32B24B2DE09219FBF0FC3B9E0376F5026558D5752DFCC73894B4261AA83B0A4EFB890F7215B50DAC1496BF67F1AEEEA31B3C8590E5DC390311C920E5472211FFE620000C306339A71F19A396B9F1589BBE9249E2A7FEEB1C56B42B89806AE62ADB41BD1AB93672DF5B426B447984C6FD5D82B9AC47AE78E2E1B02CEEA327DBB8F4D25258F0A53480FF68C788F133F02D923CFF658DF19D70C5D5E2E90FF659E1A5C4AD87EC5A93910F883FF77998D036EB5ADD91A6F56A78ACFEFD564E606AD2C93AF20A65AC03A0FD20C97BFE905950B22C028314F52F671CD0B6A268703EC909997B70372408C8A595C8DB35972193A76D5A39C1DD190955099DE507DB1A0AEAD1D78104F551F2A5AB25D4C53A1A5858EB2D08017909C4818AE75EEB8FAD7DF222415F76FDDEEA46AB882D626C23BB19080950D1FBCC8326CEA8249F13C669BE3A19754F8FEBC08EB0C4EBAC03DB1E54268276FD8D260E6532A58E41CFBB4311A48DB5459A2CCC2D27AE527144394371540A0150590E9EBC82325B42E403E7E857463E5757952B856B91DC642F4E43322BF0EB882A8F6EFF306B4004F3C183E6D4E9A0E7902FE1EC779CB0A7760720E036BBDFE765B2FEA463F262D87DFA5ECD4C38093F4993FF57AC74D11224EA30584301851EA36A4B86CDF186C96111E3449E69F9426DDA9AA6C29E409B4CA7F8DB95CF4BC202736D3AC884B00760CEDCBED1210A2EA017FAE4AF4AC082AC1441ACA99692222D0D37751D4767AAE64BE13B4C774FC27628E018AEF407D1AE64F03F91127F1CB924E2E1EAE89BB1D7412C26C629203F3ADCBA9F03BD213AD4D583EAE1C88C20D80149386C566936E0916567774B1276D0DA8880BAADB28C60C99279002F795819F3D8E2C58A58200ECD94761960CFD1A0CA735D67779341890F7888D5D0D3EAF5862A57998D0C6BA865AC2FC671885D84516297D03EAA021920AF521D448D8E9EE71B7F840D8F0C93218EE0B5FE07BADE0BD9EC6D1F12E22C2598E07B060FADEA688B1A5534F051C77660FE4FF00F79EC9881B0BFCF13FAFCB6E18004188FCF8B8A955CE0BB3C9368D5545751DC24853D2CA9F8AF798D11FD9574FDCF3AC7A888ACEF079A7C28F875177B3151CAF7CB6E84238A901077945678ABD363AA1572736ABED0E056029E754BE2D0333D90658AEE3F797B1C054D026ED0D1E055034C7A56655A08CEBC556FBF6E09B36F0440148195CDDD775E02245891B2011E38AC3B89939D88B5C6A12EDA6C2124320718964E603BF4A5032F63C112955BE80EF162F0C81DD0580066291A92581545432A239B6670CBF6DF1DB42341605353CA5C08D88591B0B065B666C59BDCE627ECD5D51DA5C2E92C54CA247542F99E3A6D49825C8FA3688AE5091E2EACF22AE8FA5A4CD65631D1B6CC4AD98B8C89C90A8D0910D30B656465CDD5DF4B08710BB916A2AA87E33ED1CE9A383C19369DBD152C46C2A6FF075173138565316F0A60B4DD93360FC07396BBF327C50F94B452155A10B213E8F78EFE0C9ED08F588B02091B4B69EBAFC8E5FCEE4E62FA6DCE39CA1D6C924F0B4332A7CCC6A0ABD1A0F0B67CF4DB1609C13BAF685A8C9353A2EAC2C4D3F7257E9152B5E289D17BB5B73959A49F877BF7F80C76F7B86675CB1DDB21404FA79EA28B61574F456257300302421FC36286D56342E1351FA3A158764EE162CCB97543468558BACAE631282DE11B78B563993ED941ED3451E9C0C2A3A4D39F61D87CA012885DCCCB0BD17CA28186B8C9F9FA3DB738E12E355C3208E337C505CFCDFEE74331EBE36B7A90DF91AF028441A51D2198992F969E8C3E9DEF8ADF16E01339A2D701B4B8A89AAABA1CF26FA61F00B8C305EE63FDB68B40FBC3BE227E9ADD6E64D2E784F2B44EC6C655479919A11793E99F5FDF45945797E786D619935CEE9AF4BB059F69527A45C196BB89AB35C6EBCE7507C092679F2BA7D0841C6764DF494CCB8C707E245C8F10D48E67F1CAC8B047F03D921C35FDF481AD46B78B87C4BFD7895D3A7FF9DE1C29EE2C573C5FF628A28458AD7BBF5FF72CEB83153270C50C22A1CABE2E619CC68FB784030FC84EBBF12C207606751AE0C707B1927F6BD42640FB540F099816265739C43CE0E04E03B0A0DB3094474BE690439F0772A73E3BAAB8B40484ACF326918C0FA6A3CC22F39342FEDBD6BD54CD43646F67F7F3AFD5BC717FBB4F22CE891411C278FBAD56A57A64A1863FFB10B163643317B21D14854F170905CE2B0894DBCD6950130D80C047E379EA5D982EE5363F9D2A6457A3815275889F1F00BBAFC5265D1B0887FC83E1D24722BE878D5DA2D693AE0FF6CD2B7F49E4CC0EBA132A74BAABCF9C66242AF0143A01F2EA6B4163E9196015D10197C75196581E5F3D28C11CE7AE02B8361FDC6CD13643A5AFC0BB21351910DE2CA47E33BA5C0972A666B6CCE1B9C62DAA8178F0942C96A4EA7B5E30FD87C11180929137E5AA496F275F527DFB02063F37D6C29CAB881BD4E5AE9886FB9842B86E8DAA9176EE9C2448A80815C6658E4AFB2798E348324AE2E9F27A874AB05190350B2D445DDFBA4A5AEB1410FEF3C09673C986D741ADC2781306F2930B1CBA604B3863CE19BF3FD78FE3EACE85F7355BED0B41AB740407E919AB98B062DC824A52E72F8FD627B49930D1C818B5D298CBD2F24290DC65E14A683B100092A2A3BC250D2AF06983C79B7D467C3AD941229E9D89C457761C061228F88776ECC2C93D53D1697A1FB1EEAA76AC1BD3AF43FDCED744D9CB89E8A4C342234C4B66F33928D2DD2965F4CB1FB7D7A1524F6755BDFCFD8FDFCA8FCE99C67C7828CE650654CDF283314E49962A28E1F8A7D654FB9EC3B8CB997A1BD08E7FB34C44B98BEEED7B79588B4C92E2ECA0B4F72D73BC46113A6A6E3E17E07AAD79E7585D793E5CBF7D829E626C71A5C91611C0036BECFDCB2E9C15B0F52178F5A31D59548DDF0BA0F3A6132A8D8E469DD32E43779B8AD10170399CC64EBCF6B04E44D6344406807781D00ACE8933D4154BAA16FBFCDA5D78C94C55B0F52178F5A31D59548DDF0BA0F3A61E9590F8712727B0D463BABD0F964CE89BA3830E0A7794EE34160B704E43DD174D2AF06983C79B7D467C3AD941229E9D88B247251C5DB9248713F4CDCFD778851796140B75F704D95B3BFD1DB59A79A7AFE9196A205AD4B2E5031929394417776C3994DFEA258A0A2860C0F2737B2E0C10897D32AEC1EB91BE453987BFB0D96AD0FC0C44D60350AFB7999DE88624185E923276034DC7796253D4560A0F841DFDB016BD3CDD13D6561CE0A69E415CD30CEBBA9106D82F166A6D3E8FAFE3B3B1F7E3A12C32DE46CDC9F3B761CB440FCC3365B0F52178F5A31D59548DDF0BA0F3A61EE68A987833C77097E538B19B926CDFAA2EF4663EA8C7379A5BF67FCB84CDCAE5B0F52178F5A31D59548DDF0BA0F3A61FA99BB5DCF1AF52BDA8A3F2ADEF75FA67C1B0A68B253ED0151563FF3E9ED84B818BD8A65ADC13D9021E3F7DFFA80B11C31B4DAD3EAA868FFB3B8A3F728C222BDA7DBE5ACD3E4E7547C51FC3C5D1F52D950D5757C3C87424C73B63AFBC4C6AC50106F71F9BCB94E5DD2E7590F915EEBF54ABD7DFE15B25A944931B8A48D335677F87F87734A730E8F90CE07DE2EFE6D7364F10DD581FC787D1B4BCBBC70FFE0EEA85984CE65E8EEE415BA94FDA1CC76565B0F52178F5A31D59548DDF0BA0F3A61C50E253EE3FAD89BE6152298B97138219BD7E8E76ADD1AE54887575B62956805CDB759037797E2E265C7591D35680B23F32CFF71D04ABC967827DBD20CC6AB324ABD7DFE15B25A944931B8A48D335677C317E3E5A8F0A31EC1E20336EBCDF1E07A3084ABD06F2F799616BAA890461B111D5E409BE3720F51CE50674C5CE75F649ABB9892EBC26A3B4676945AB51325521B25805656A7F2C5C1F4C6763F52DCD75B0F52178F5A31D59548DDF0BA0F3A61F6523210C73BE3747CB103E43AECFF646852CFA6ED371B71EB48C7639EBFE67B870A05637CEF0A50AA603056837F1438E56FF31DBABE17785F4443EAB6491F355BB58B31A3538ED0E79EC3752CC1E4845B0F52178F5A31D59548DDF0BA0F3A61851B028CC7B792DD33BAC70AF19D92C0078A5F6465DADBF7A4B77CDAC8B435CD82FFC7AD55467603E162F5F023C245607291A6F92798A2F10DEA3BC2C4AE7F67E62AA9F07E966C75AC39EB92C2D6804D73A66CDAF814D9C3951EF3EAAFB37CF80DB60ED2FEA32964A78D91D26C505813F28C0DDD34A7AC1BF58E0B800748F57F9CBEA21698A4E8B8DBACF81DFF89B81D668F097B50F3D2C53F6D5BB87BF26F332BB77DBB8FA16F618B2623503825A51FBE78F5A9FD23E4F66A4F98479F1A9ADCE09970542DADC30D964CB1A6E2BEF2EABAF0AC194EFBB7ACDC0CAFC58AD4C89152AF525B07851D7CA05B0F9944FCFB6EA4B86CDF186C96111E3449E69F9426DD11F08A32C3CE3BDFF37D6E3EAF2AEC8554E5F5CE52A5F92A9BBF9500687796E07B3DE3E23431A700F19B9907933147F8C1C3B2FE45CF2F3E244E6B870164173A924DEC731D64ADA7D6D100860356F092AFAE25926D89EAE216E9C94CC089F18899759E8396F5B5C1823C607B153AD1A0CB399B283C6B0FE993BA234C52CED8B4DA8BB5DDA77E8A59FEC85982182E8ED31E22070E06A125220DA1055112C0430CF0CCD04BB0C9793824D458A0AC53D3B7EFF4D3E7DE93D0D718D2035503A5099AA00B6D34D85F57DD96EF6522D370460D046FD36FA255D44A1F7C8E9DD49B57C7769A0947A5C2ED31055A465A5E8D3841BFC34E9DE955C79ECC5BD0EDAD29F427C32C4400D24E24F9EFE247D997C539011A472F70239B6FB2F895E993EB65470502CEC1E8F9FD6222E3E4FAACF6EDA0D8848F94DEA596BEEA61D3DAE7ED2713AC6C0134FC088050348C7B198801524603FFE17434BBD6A10A72E712EEC389C75ACC00E8AAA665C8418D1E014487C85C13496C31DFB6E6DE94817EAB42FB08AA7C02CEC1E8F9FD6222E3E4FAACF6EDA0D8D4887EE342362F29F64903BBE86753D8F918989C7F43EBB9497C7ED8C082881E321EE07FB62E7A4D84CDEE5CBFA9551C37E10CAEF20F2FEA31ABFA3824693197DE6E99048108EE9D76FABD77910181ACA7A274E12E59D44667438E40A679A04CF6BF6AB46440B65643CBD3F9C1FF0841BF3117CE42D12295D680B64976B9AFA359F0289F2CE66278B7CD7D6791F35249C36547BF8D6B3F8EF31AE86C5B9A1EA35F98FE01A31E08821058D69AEE1D3DA9DD80F93EFE8261CEF47DEF66072ADFA09B27DA881917A28E8253577A12AA662C07C1D3755E979744152E7C2708D437A77AC0AEED3B17104A27EF3E9E62C276BFDD80F93EFE8261CEF47DEF66072ADFA06D466652AA7470DD6A10D7487465F78F1B9208CB7B817A3F59C802350BBACE174A8FBC42E284F7F104802C0695E44FA1DAB2E67B6EAA637EA154F2A33A0D9D6613069C7A234146B28B6FCD7F1EA9F8F5B38922F55E96BB8A50732B5B8385BE3B8AF6FF3A4596FE7B6626E553A5EEE53DE7C1A07D2A16C221EB34C037AD1F7AEB461A1DC99712A45E829FCA1166857932D405BF384A7E8CA19CE4FF1630A3721BA1D7F58DE5300FD70AA6C91F4CBFB1B745254FB3A5D136C29B458FE41CAD9944FAFA513893A78D1FC9CC74C898E11E6CAC28F4AD3A85E574B45E338032B911896FD00E2581218A4A890F3F0C6F4BDB5DBC0A777C3FD91AFBDF870BDD9BD3A2DB10A4E3D08FF95F4D29845B4A6BED699149BD592DCFB06A21A5CE706E3C8B0AE2D9F6AF062B51B64E0A5FDED1D1A738B44918E6BFCF3ECB3A3761AAC73F6439D0C27B9D01CAE03D852BB8F3DEB1752924C6020A4A5DC38C78B932107660436C74333001E6B4A3E6FF9EAAD620029364B73A43ED596442381CAC1E74CBC4CCAAD5D596E5C1869C9A043E845DD48D07C57883879AAB0239B30E055EA80394CA2450D293D54FBFC411957EA632E8F1BDAD0C6F63B2ECD10118F9A5C56D463EF70E6BA481ABCFA29330C37283DF676101CD5FC8887379B3ADD6CD2C46D1FA6FAB4609CAE2921E1F4D6D21E0D13D0B689F9C702EAD429F0C89118ED0677E51A10727B8D0F7E24DF323CAE93434E552A4AB81FE31284D173AB286A2F0956E04C3956ECE1247E8ED0026C7A114E55CFCE24E2A506572CC77481EC38986C956F3A489B509851460D695815821E49B70AEA3A1237EF0CCD04BB0C9793824D458A0AC53D3B7EFF4D3E7DE93D0D718D2035503A5099A579BD3066E00A2AF59A770FE7E7259E6C66D53BCB6F62289C02346C3023196C94D5337834CE431DE4479FE150AB2828FE48AD42C771AD65DF2E3F4172C12ABD7B098B37D10BB88B63BC5E3CD49E85494BCF650C9A52C3A95F21E43415D231FB049A80138855720A4BAADCA8A5D570BBB2A25ED378722038D6FBE874F6B645DB36FB638A64566AE30B967EB1F36F958640E50E5BAA6CC7364DBEFAC85C3298280D553A879BAB18DA445B66A88041A8117398A0FD144653BEB6DCBB63F27F4AFCF5B518754369C26FE4396FA539A8DC17E07475E8F6EF88303C22C7CE7559F14A925644D7DE518D971617C7717437E34FAD9E69A5DD6EEA6AC1740029534F6D4C6ECF295DD2D61561CACAFDC9BF8858C29E73C54724E3B3EA4437845C03ABE8912E31B254CF5C383BD50C11B039DC6AE3C11C75B2383E21044F97EA6DBE2D02F80434887496EBD904EF99C10ECCFC7C0CA49692E89D41587B4604352C9B4C0717C48ED8631E608F8DDE85F56FBD9952F9934446856DCD03B2DAA5A26951E69B3AF470D76201CC7EAE77FEB4F8623CBD5C7E6D2A61D3FEF6EB2A43FA90AF9B62E0AEBBB9AD04845F8E803AA9F2C135E19B3DA0471DB8306F575733C38CE882A2D5A6EE9D6188673328FA453874085F35375710B2B16207910A7C6BFED365BF886841B8861B240626F45C7D542B4E74E202F46AC75CDB8D2A4153B8C7796D19E12736057EDB7581C513A415E4B4F7B156F9E4D0D2FE48200851E23CC3ED3295795AF84D13DF95F8F22214639D6AC48AE4176B8DB0E9926164C18EB7A152B14D1F2290D8E7D38D63759E30E2F8C4CF5B456F8B06DA8C3D768B22B864C89E1A7A3A1146AF37ADE19DA4A64B7C32D5790F287AFB88F3F110570373ABE8877D2847CBB96A84D6AB67FD90C25CF51AFA84EE0E4849C4A9BB0D66534DEDE64620BA7D6E20DD3E41E00B6798565DA910189DB3BE4BA9860894A53B9CDA0918F71684156CF631280BECD77883B477E387956D66E496218B8510894D07126785D43F486129A514435F5D3456E6DB4F10FF02BD0D3FAF705E32A432D27DE1453D495DB3EFDF1F25B0F52178F5A31D59548DDF0BA0F3A6182622ADEE0C2F9D5CC6EA248BC8F3E4A9BF0C019B433766DC8D63DB4DFD02C61C11B08C25FC30069FF545AE0E10A1379213D437DF597B5BC17050D28B3A4BF790B7BDC7458E45D508D1DE6D224407667E13DF33095E5985E3B2CA59EB613CE30249BFB072271DEDBF7E274DBE3B82D9CA652EDD0BA47C01D922ABF26A53B61350B1C1C4017398A092ED179929A5D6BD935F04948A5488AC8468967832A2C5D200035583584D8A7B7D7B8D98F1B330A7ACE2B6FA4E99157FBB988798D376D353B4E4E2670DFFD12B1850592AD7BB563D089385D155EA7B2CA31E0F60337C79500365AE9561B2046F54E3A4B2070965FB393DEFD5A50A882DA23D3F443D909EB58ADD9F12F5468A65286B1795F0925A3C01D729AB9256C860EF0505DC14F386376BBF588CD1A13AC0A95C3B0B7118C9013A8C1CB9B93EFC5A07BEBFDD2754DB6A2C0A089D17F028E78C40B172524C3835E1A44CDFE00EE3C48E87B61BC74F975E412A8AF1363162731C7FA5038C29F94B82B92C7731F824F910CF51D2006EAC09EC7F545886C93A65208E946CDF6FA6126559A0D4AF6FB48B7F754E31851111CC5B054A830F94B22856BBC9866812C49DFDC7F04322D90FBC0770751ADC155008DA28B2954209822AAE05AC882DE03BDA2E9D22CA0C974FFDCD176E373386E138DEE4A726F5403EDD3698CF8C4ECBC36D9418332A00F932CF66A809C9C4E89F47C5D2012A5CB3BD78A3714D202454533B7DA5C2E92C54CA247542F99E3A6D49825C8FA3688AE5091E2EACF22AE8FA5A4CDAE0B131F72A6B687544CE27280678CB4371AC190D6A13566C5B7BE108C07E04A10C26F008229CA00B89BE7FFD70E71E365457EBAD77AF9E2DD10401EAE6FC8D3213BA4BCB0BAD7986A94EB333F88940B640B7B0A6CDB2835C9A0EF3A5241774080DED89C9C31E4B3B7712D99F8DD1493A5AB7CDE8E493A08784794806F08383F3524DE856792FCACF108FC1C98B22BBF73C452D2EB5EC449D279785792274ED0119B67B5AA6A5158EE119DA181613F375203ED8E7D089B11059174BADADFB285D07148F7DE01B41AED70CD1AE270AACB25C43515DF9D8806E6B7EEB2AEBAC3AD70D9B8894B14F2EE058DBA9A30E5852A6D8EA122B04E5F03DDC6DE4ED8D3C5B593648CF930754FE985CEDE0BAC5AA107498C34808AC02AEC8033B95A40F7890ECD450BF13F9DCC6EA215EB0A167A98D726A726AF076CD83676EB8EA6EF6273AADC179CFFDE5BB79EAAD8FEAD7DFA0AAA3B78D887D3BACA022734C5CA856EF9DB6C041E85627DC21B93CBC6F6DE4533EE0C6A63D53ECA9AE9543D4C4A8F39D700288304DBB434EFCA3465E73047DDC138E59DC09F541C12F231CC3CC52FC454BFC489A4E0AC023596F306BEB658DB7481ED4C7665959A33E96476BBD0EB6E12B11E7E1C2F161F7FCFFEFA5C6C893C2849D994504FBEFAC908182AF541CA4BFFD9FC5879BF023F807420B455DFF15A3B3B3C31D98B046520A06D81117C4528903E2DFE431AFEBEA679B3D39A06265570490897D32AEC1EB91BE453987BFB0D96ADFD8199703DBD2F5EEB0C5B3EC37F79735B0F52178F5A31D59548DDF0BA0F3A617FA7DC55811EBE5BA6072440B2EFF51C47A53EA888AD57BF23793E671E6D495631BEF7704D01576F6ED6B1021A22F064CC69D2D157D182F57902B968C57986DCEA2605CC04271C14B269CAABDBC46585C645273D4F8D5A02A0940BEC17CC0A7D68DEFD5059CD66A112EF30F11929E95C80FEDA4E527B210AC6805F7CF1B5F327686AB7F210039B3E28B057D5E453F2A2BEF2881628216E0F3C5E6BBFC1A3D1B4A95B7088F598D07BA9AA2B05A751FE5A4514850F937B2139AE394BD7EDC4D4D98BCF8A573F2CBCB7E2CC288ECF7FE72B99A93CD708F380B443EC4AD28344C3E34F2FF1D7CA058C807521B1ACFF55175177AE2073EC3351734D8278AE66BFD8E68D39197FD11759CEEEE718D7CB0A20F0570DFE6C68F065829A7B7123D9F1E2E734BCFDE476CDD3C5108D6E801C821D9D9B11B6FBD79D4AA9CF4421BA0C6AF8CCB652786DC8D17C788E78EEE76738DA1199A898FF18C20F4D56E0BB9C6981A299D9F294F13A902A7736D7A8EF125B0BAAB2C06F1CE1F93BDA12ECE709FC7BC09D82ECC0BA28C95BF795B5580395CA01E7B916E4C63556BBCD7ADA11F6210278BAE02ECEC8E0F8497C882EC46E6BEB9D6F239D5593AC2C5ED9233E12545254FC78021594D825B8B0228296EA7D83C618A46617046C8139C5DFDF65571924186B7743769FCCAB5088003CD0E0D13A84A720D807A1C8275AF42A0F1E38CEBA9E89CFD066DD43143BA8CB2BDDCB70E0EA9C3D050DAC06B957C3FD42A92B17733A9669CC8825EA050F0897BFB8654CF73FD3103D8E2C58A58200ECD94761960CFD1A0CA735D67779341890F7888D5D0D3EAF58F7BF2D1CDC34837FB2DE4CE5917744F501A61CC88C8B2DDA88922AE71DA36A0F4435F5D3456E6DB4F10FF02BD0D3FAF71D813B7ACCE8E62EE036FEB59A615A85C48DFE1E60717DD1252497031EA5BA921A23E25B7759A6945327AADF2DD88214AE516BE150ED58AE2588E9E60094D7048FFE0F79EF021564D032E21446D125C719E9F92579157E46C49EFC03F2BBF46364D076BBCE9EB7C4D0E9817C58DD2441C865F7D47AB655C4E4A9D44F6F6F0DC1E928D9919BB223FF7DC2EED56A9EB6A9427629FB1F2ACA6BD8694D3915A5EBD8C6727D76F62E0ED33025CB0A96C13FB8358E4E4BFE720ED34AEB93CA3A2737D81586B6137F7449CB865BD9DCF5B007D59DC462B1F21A05374AD945E7892F084A670F0AEFFAB2230848108DAECFC19A5EB942B4505905296716388EEDF0AE0046CEA6F33B6E1ADAD9A4FEA22075DE973CFD3602175F2E21730C0A2A2EED60E08F326A35CCF51DA5C2859688F5E1F5DB16DB9188061D7279652BB5F2256BC1F538B026739142481952090A0034BA90190127C76D7CCAF353EF305B45C4E73E0A4B9B2D09D5BB07C43CA57844AF742957A2E20A6721F060A8B75A9FB5F72996637A507316C08D4C0A5DD0517832AE2CE4DE6A0D6EFEA98D1A2D10BF7A767F7EBFACE7F1730AB32D79EB96A8AF011B94CD69234B9846714C72ACA1D33D60647CC411DA5C2E92C54CA247542F99E3A6D49825C8FA3688AE5091E2EACF22AE8FA5A4CD48ECD595B525FB58E27E72490485BFDD6204C544522CA980EB41E8CED6912D75F57C23E0C19AA7A1A27E34B24E3279AEA289924F6E23640D7D2176D686C68539A1350FFEC701C2B233B14E09496C937EA6D457FCC1FB1FACF10C2B7F14FE1D2B2167F159E227FE8D85D1F305413086E863783E3A3D803312512FBBA240298A425B0F52178F5A31D59548DDF0BA0F3A617630D9B9740C169D8B4656DF6008E82664ABD2A15AF8006EB29485D159B6B9C36E982A4D6B76BF9EA05B300E2470C8F472F8FD627B49930D1C818B5D298CBD2F90E144C6B6F19F93E6AEEC0189B8946CF8C20613CD78024D3306C32BF6B74B61E05AFDD34FBDAF51C2F812C62DF2DA2FB787132026B705FC10D9760DFFB0DEB064CF1CEB156C8E1AE632F49906B1E1EA3475BB1BB36E9AD906CD8CF36559A2D8046FD36FA255D44A1F7C8E9DD49B57C7769A0947A5C2ED31055A465A5E8D3841BFC34E9DE955C79ECC5BD0EDAD29F427C32C4400D24E24F9EFE247D997C539019DA222E611379869AD081ECFDE5823C789AA97651399F8687572A5DF369E446C1C984FA7A917CECBA539AF7876F498F548374647CEA76FC7A51CE0DF25054BBF64D2BF3C4AE3D53E5969DEFFCC63D320848F94DEA596BEEA61D3DAE7ED2713AC63DAE331812F6BD3C6D75B795D96CBFF121AC3C56ED8DEB4719E47833B745267754A4C481C18DD50A161CCB03D8A067FBF93C4ACDAE0EFE39DFB12DD21CEA7C5C29441C7100F3C60878950202F95EA7EDD5367A3792298562FA882F34BB97C4976F74FF7A2E7715D2D03A633AAEF37B6027C66F78001BD6AEF522EF5EA68134C48CBC6A5AAFB7E6947F396A89DAC4857DED3EBA406908C3EE0A859A6573932409D841638D34583573978281343DF9C3070E023BC7653A1F9365FA620A0DA1B2EB4D366D0467EBC26DD04A76D07CA2FF57D285B0CEDF8FF40AE385DE1B5DE891AF68DDDB0AD8063D9C4EF8D416A6E378C60EC3367260CAD219209FD8589A6608D215E2CD27B56E4D2E94994233D78DCD479AACF3695B5EDAA77ED01260D7A5265DA5C2E92C54CA247542F99E3A6D49825C8FA3688AE5091E2EACF22AE8FA5A4CDAE0B131F72A6B687544CE27280678CB4371AC190D6A13566C5B7BE108C07E04A10C26F008229CA00B89BE7FFD70E71E365457EBAD77AF9E2DD10401EAE6FC8D3DD80F93EFE8261CEF47DEF66072ADFA08C4F39C61414EA2550ECE080444DF2A0213BA4BCB0BAD7986A94EB333F88940B640B7B0A6CDB2835C9A0EF3A524177408A046EE75B6739A7A2DCC6F3AD8E9EC7931518157EFABE2D82755B7CC4600A4EF8DEF8A95AA63D95B2B79067729A2322C2A7C8EED97FAB7A8E8735A57AB36154B3315E219681F77F05A8631D62FAFE55445F4447A0A91F1A23324C0C24E11A1D7E41D9758D5F016E4F5066371247CA28EF371D5708E10B714F4A38853D9D8E432A693AC2E157DB08FF30FB46B8B877A38A4297ED5649E4EFA63886F97BE49EE9B498C3322A9B946C06C5CE0E5CC9AB1FB95EDC53FD6E522BDE9057A2DDEC95942FFEA57A48827C8B74D2ABA4F065D1E6F48EBA8FD77CED033270409D9618F9086A56D4BAAA0E666F5D680DBD228EF82DCDFF67BC1A014E2244B99CEAC5CF3E83781BEEEA39C6291E6F16C692B6836541C4FF058620F17D8CDDDCEAA2F85D37255C1484BD3CD22EF2AB90D67067BCA6197036D99F18228A7DC2B6AF02FA4721357F95F736E121944711125C933C4F357814E6CC29C1918468D10B73B902CB05C196AA1BFF2EA2FFCC32E443EEE7F35853436B632DC8650E4C0D8BB8B99696FDC4EDD9FB35D048760FFAD4714247BE142E2891DD3ECFB11B511BB85ED29908FDF16E36BE1808C866067F87D9C9287AB88D6D440F547256240EBC9EC611391AC64DFCE9309C150B13A3970D58CA61B1831580FD6877AAF5AE5B9ABBEB8E624CEBBEBE7EDF3A2681A47EB0172347D42638B40CA4020BF1197919F7BB33E99F5FDF45945797E786D619935CEE90EB58D3B959BA8FD973BACAF2A32011B6A531C419C9F0A65E1E76607F0CAFD06D2BD87B0CC7D0B5E1B77F7C78665B5D325C43515DF9D8806E6B7EEB2AEBAC3AD70D9B8894B14F2EE058DBA9A30E5852A6317EBA7F3A8C28C5474BBEF6E4C71B24B17267AF12567255495AEFDAE3F3749E8336BFA373B9FD1C19D2F8F3955F5D830310F2043B718B4D57D689ACE1F41DD0BC91413973F1D3A4B173B02ACF433F863C55FCBC951BA1F770E25E8600C8131880FE9D37F7D00047EF6CDB9EBD9CFAEEC6DD840A89D6FA8D9DDFAF764255519A99CA040A869923FD43ABF31EEF7E9279EC27736687C42807DF5E4551AB551C05DAE114B8BA1A9F1A2DA26B7B1455B1E2B121D208F36A1F69109894F04580169A9D6793B0FD223CEED13A1FB69844E7DE8CEAF168E331D6D1830701F914A26656A800B525F777E2F96FBCA95A590FE8BB74D1AC98D9D158ECD57B03BFEF8CD823B7BA04100AFEE82B76CF2B9FBA1D1B06BAD069B4C4D08819B9F02417C4E72F00CAFB228C3806E81352733AEFC910DA48AA96705B2E05E68FCB314433D99AA0BC0D7DCC01E337840060B7B48939B816E2B68EE76AE01EC52257429211EF7BFFC68D3E8C4F4735D77661B1F85355990DDDE63233E2EBB17C11B8180EDA9A89C0482A5AD263A7097436D01742E1CE9986466E974CE29BACB0B4FD66D7BF6039B1ED9F294F13A902A7736D7A8EF125B0BAA944FC1A4C5CC3E0DB9A8481485D8528689CC0B8A9FDD4E7B570CE3B4FEC6246C97B4A3601BB42AC1378FBB68BD395534AF4E5C13FFE1207755A2895A9B8EB0774838529E781022A1C80EFB9A4ECA12D20AD938DE4CC808CD99ECC0F389F2E6CEB9B3A107733B86AE2D695912FC51D4E601511B05AA0B6E75F11938C8AD6C38371275F17A3D727417F102A4AD2B1F87D79DCE910FC2CD36C575F33143D1907F852B61FF138FFAD6AE8B58BCED4A1FDAB82A433AF2390CB56BA14CF55D0EC52DBCFDB55D49F4531E822C2B25A09F48A59C01CBE1E6C21188CF2DBE0AD7EC96C5735DD641CC5E591EF327B10568F07C2C35C28B783097178556424C4531BA4B602C439975C682ECD87C21E65AC8BEB0A5E978AD57EAEBBB1FD89D2A90CD2D17A1639B774CFB632AC8D754D6E5EE2D23F9471EA927A331815EEDCE538AF03B7DA13449692E89D41587B4604352C9B4C0717C79F19F146E372DD214F8451590DC5D2FB01C75FDA21747B15E7E98733C320D31FC123EF7DF9DC9CF9D22E96637EF378987598E649BA0FFC8C1816541B4C5CF8D5E06094ED40AF35AFFC4C92CCE7378D32487B1546CDCB27A53DB5257BE243B58559E383B34B922080268B98D91CC0982EC8B0AB75B3FC3E41577A712CA6D320320BCF3472C5EA86E94ED1BDC211A50252EDA4017C5EF9BE3811BE77A221B0E9A4A0C5F36AF4AB4F39AF51D575A3BF06BF2F9C2D17A98776A1394FFCC0DC7BB9ACC6C13A7F20A1403C9A57958DC53A0421F4E6ADB60CF94D46ED28094A96639F119807E43D844B84482070858B89B9D43089CD65AAF33E33EC7DE3F14DD59F309FB8C37B5446223ED392C9749FB62429E56FE066BCC427AF926C3E9F72DB65F1951ADBB5E7EF8051DF2785994D9D08744FB3893FA40AD05974777EF96FABA3BA6E99368DB582B51966E470E17621AA4B0C23EB7FB26B147BDB4776F15E3D187767634819F59BBBAC98BF65873C48B7C253DB025A4A7BA35DB3D172868CFF12EEE83E78120391A6F69C0605BD818EC7FD7FEAC8D57F20E856CC111587553AA0E67D06B0FF484DF6FF7ECEA4F665F7BF03C39BB3428ECB4EAFB8CF06B1F65DF4FE0C245BA22CD9C64B8A69572B7BE140A68746AC94DE3B5AA81160D326ACDED65958625B8D871CD4D52E9D71D6037B3DBE96BF0527FFFDF646D4347B9B6D633958CC23EB7FB26B147BDB4776F15E3D187766AF6B69824855FCA7782ED76717D96A74AB0680AC4387D390079F45049E67634557B39879DAE397B9119C03162BCA7AF9160845FA656C910A87D4E5A0DF8FFC20D5BA860AB6C2BBA04BA28E818D119A87D8556E35CABF6E2DFF1D75F4FEAF5EA12FA6AC19938058926C1E4D4AD3D1305288BC9DD983F5FDD839ABBE82B4FF21DBF9328B99C16A3C212D0532181A061A4263826C808ADC10DC8177852077C3D95737832884AB788888F3C9ABFBCAF9AD139BB3428ECB4EAFB8CF06B1F65DF4FE06DEAA2B49B3CE7A26101FE4B8F695F948177B2220888C07A889503F8875AF2859BC094266BCD7A6BB265B974AF7141B0D4D528B339D99F2C8A7BBB5D3CFB5630E1CF67D1E8B8586B6BF17EAEF0187950529F1496A9E4A01496C7EF9700804FEF6EB51C4A5C1BCC2921CA8D947F2724DB9F010F62F081828AC896028AE6B9FF2EE4A05EDFDAD29949A6416D93D973DA149F010F62F081828AC896028AE6B9FF2E43FE421CB812C6736ED449E05EA0AA7D39BB3428ECB4EAFB8CF06B1F65DF4FE0520A8316264FC2464483945B0B567E1CA16CAE87DC30A142EE104940FE2A1FFC06CD5E8F056262AB1C3290DD82ADA1E2BB102E6C96196299C036F93B0E9C9BCEDC1EDC7C415AC0D44BBDC5923294C473A3166DC2F3A0C338281A095FC9003318DDBA64189E9F39F65E203D59729FFE06B9B3A107733B86AE2D695912FC51D4E65CF6560695989E6307948549F7A404C537C8A0BA2A10BC084EC9C41E13C8CFC8C5589ED209CD1E02830DC6DCDF2957F90D72285B261D97AAAFFB29F3D3017B0AE31599C8361179CAACC680DDC60DAE5FF90E202A70A8860FE4BEB50404D32952EB1F6D1F4BA5A3AB489BE92A87C5BC9C659D8FCBFA632FAD238E874009F6F579B5AE3E6CA44F68104DCD6DF61869959AC6278154A07ED3CCBF1CFE879C7F59C0FE672F5065AE00668C41EA9A5FB8F4EE7F4D0D0949CBF5E8533862B7FD198582A1C8F247CC7CB780C54D658AEAE7365F5C31432438C46DB7E73994CE33B356182BD4859DFEA352845DDDD367EA48622DFD806D55C9F4E20F12B7EBF3F1BA8C5DF56493465EF98E516179F96A34B2DB0AE5A57729FE89EF4F55AB9DBB6C6C849ADF63B229FBBE3755952AF53975A5419CBDFC05728A042C281821E3B48676F718E3F1B8DE4062B86058CF16E12B3DF98E1D0363094C08A40AE9F0923242665674C4B693F0C789F0677B1FB1DF0321DDAA3BAA356C7C13F38D35B4E4FA53E6D37A19807E43D844B84482070858B89B9D434CD33EE6838BCEAD9E4725D585517082E589EEF6554FA5D57BF2C2B8B51A111E2680EC36750175BD9CBF09788D58E8F294B1B40D3340C0997722398FBEFF26BDE99368DB582B51966E470E17621AA4B0357C6C35A118DD8078374FB16D775625BD71502C091747F2837EB8233BA040675F56EE92C9C21F4FA3D566B0F58AEEB4BB4E91101A62F845CF8CFE867C5676FC589FCDA2C9E3C7B4449E2E2034EDB517D7506664B389CD225C0E5ADD4337A0BDD8A0349F2CD4D07C3B5B20A9C94E4A9EE39CEC37EDAF82480550BA7979D4A6596A022F5747C7767398E3DCEA56CEF37483A18EE239E82D6E949E27E39C5F8DD1BAD4E847E6FEA479120E5D4CE50C069FD0E118B176DF018C2E9560F8B8E7B545DAC8D8719E2C9E4F65E6290E694F86F2E4CE7AB3F52A354E142EEFE1F6DB9BD6552447933A5D328C2DDF4F75005EE359D54D1FAFCB3FFBC0E0E57492E7A29569357C6C35A118DD8078374FB16D7756257916BED14DC892F03CE6D89AAE35C5EA937538D53FB8B1B998DE89E2C3D0261FC022426E0EB711DCA89DD46D69369595E57D53C03E55C8F18725E07CFFE6442E5E32AA05B15F503B403059A9DD9651FD27D2B885DA5C522505E1F5FBB09C17FFD82BBFDCC430D63758DCDFD8C5247D644C3D559108EC85A32E9B724E2AC15143F02D7AF19FFBEFE70D75BACCC199752EE4CE7AB3F52A354E142EEFE1F6DB9BD66A888DAFBDF4ED7893361461F9E6F43BE155D81DD267940C1D2386488E0744089B6768CB0BCAA826AF28A33DF5B227903F12863ABD8702969DFE677244090B7B4E2063B7EF13AC6AA0E45C5AF22DD3216DE0B4B6B5532C75F2368A65C4482DDEB7D53137CE0A99A949618DCA0976EE96AB4FA47D42DF231CF3440CAA39FF7781AF4E26F76DAD47E2C296FB8A972F272137FE5328C16CE73F89CC149BB188545CFDC8923185FD01E1DEE40BF0A070AB5DEB8313DD2833211216BE343433DEA39FEEF18EC756A90DE38F63899AB05EF5881075859E3E6A91ACE9E0A408E0757FEEF04A74EE84B37B2E508C5C8FD67D8C6F6B8E3D6F1A6A955835314EE0B5289890FB910BD0C8AFE1A00306D862A9D3732C42C2D0EDE3FBA1443AF2F0B733D0C487E5D93B10B0C45217D6989CE274A83479CCA64E201E984BD5F4B111D689895A39E2583BEE800C9D0C1C4F74697CF6BFC20D723F7A221693D33AF007E4FF4C3967DE9AFAFBCD4A8D348E7D3C53D8B096BFE155D81DD267940C1D2386488E0744089B6768CB0BCAA826AF28A33DF5B227903F12863ABD8702969DFE677244090B7B9AC0812071D2F23539D5E0895219298A26E4F0C7F389341C9594E71A12B684EFC825072E503ECED440C1634BF31123CBB02BD3A06B1070452AFAEC843D0E54487E041DBBB23E56EDF37EFD7B133E88339C1BD4B4266271634AB43F61C17978553AA857E0173A4118001559480F5F9DC3B179944B79C9FA2491CAFE41C56D21DF9557A2658A0FD171C50495797D0ADB0DF13FF09F5FC2F4122F712DFE999A5F8119A52B444BCABCF8AAADF0D9C2F9A64E23A41F2720D95ECBE9FFBFCC0A5F593E2CAB7F0BC7F4A276777E19B7B4C09FF1589EE720F2132921A49A9A29698838F658E1B69E0F738F47A1EED119A916B538CC328FDE0E19FB158EE9D04ACE2286A6A716AC52E292FA20F57B5BF723717215F683698A3217B0880AA8766AF605D5BC58F6C9451549A1516E5E2CA37ECE1F9A289433DB28A8D06127C516335EC910B20EE3D9D8F9BE786D1CAA957D8A32A2955653F3CE8026F3D7AAFB85B738428732E45ED1A95CD900A3EB18603B5027766B9860894A53B9CDA0918F71684156CF637ACE4A690E6D52F687DB850D3BC970B7C20DA783D64AED8D98655B15807D03C77B3DE3E23431A700F19B9907933147F8F85A3BAD3537AA3CABE5D9720730A2E3B86D4D6FCA28F12BAA49D3BD93BDBF5F516F6C02F69E6064FDD5521333EFCB21AE59977C874F2C2B01DA361922FE6477CE5929FE39750363EA0A812451704DC646132035F5B13784E4169351DB8CC05285BAD843FB04097BFF444B1DAD1C56E82658297B26C51434569814B76882CFAECC9149BE5B15FA8CD666E5DF693C6ED665637A0C01B88753DCDD949DD4F4AF02D8C48CE7DC2F912400916BD4D8B921C806508E37843709568FF38810A68A6874F990860D7234811D2E8EF98951248F557F2375DD8E3172472876273C48CFB58FA65A4BAEDFA04AAEE677475D538192DEE941E51ABD98559633AEC8CF482236E94B0DDFDA785D4C730E61D330EEEA33364F7CF47EAC5D5560ABC35B95E76A45C1147E920968DCB6F912DFE114D6D40CF28051BB15D0ED44CD93BBB508A7D79DCF2F033461E32B0876A0EB74649492CE53F8A273635B09A4A46383CF5C7FDCF737CC010C03DC3C869F913CF0735E04C6941610E54B727056F19D7E92FB5ED9206B49DD67032DB094CB4B131082A1D1BE021EEB9E115D894301DE9C9BCB27B60F732FC5DA09AF7DCD7C5C4262C0E5EC37E97934526A32BFFBF3ACCEC4DBDE5B2D54320BB9275B196E1DC41EC5A7961C48D5283E8369F1FE554CDD06F4AF0D139EBEE665A0900F0453F6F976A07B01F6E4BF06E66656C7F2097F3C232EB4234A699F016499EFC1734D340E6655771D5A3400FF5B9108079986D4E18D261B110FAA41F7BA85485F95452A247B541EC2A206CF2593C9E618B892BFD5E4740502054CE2F4D14D0B7842D88B844AAE362A7BA4B4C5B95D1BEE3BF94A8A5F2171019E9E6467006479DF15F36DE3D32A2B113EC05FE09970542DADC30D964CB1A6E2BEF2EAC6EC558B2781E0A73642F24AC2EB76A82E7B7E67F5E7B09E42978833B205CD1C5D28861F0CDE688F8482E9B236B937984146610D081830806CCFAFA1FA0602A27388E6ED178B8EEBB71BDD62056E30609C84D16BF611CB6D456FC9EDB3D5EDEC6132B757DB24FFD46DD96C6762C2A6B6E548D5EFD5B510003DAFB191803F64D1641BC1D246464935C9641E6B27F73210589C98DEC2C76ACE1D0722D35E333AD903ED41398B57D253FCFD6BF0DFBC47F448339AD805D31D117EA82209E74F1CB840B7D9F5F5C55C735C1591085117A0E83F19804CBCE3D0BA73E5AE87B50804398899A34DD32E859C546BFF71B32DDBA1A1D2F1E58F75946D3F369FDC303E294A0926413A3C9BE63700CF89866B72B442FBF4FF9C5864D949FFECB4EB2A73315A3EA61E9D6E61041819AF06131C40B2D9097DA6DDA5C45ADD1DB5363B61448E48216D8A9C50FD1464353B8356A0EF5689BBEB4F475AD703E8B164237CD904D8096AA753DA37527F27154AFFA9C7859600C6B4764E01E5B2B4E7947A1433A2A0D8C9EB2CA0629646C3E24322728B1D41E2F3194FC14274A204C031353C09A71A2003BF18E5659FE623674BEB3BF766671905AB6251BEFFA1B4756C12DD43371696B62C07E31464AD8197844A6C5F0BDB5AB13937C6810896CAD5E606C3408FDB1A4F04E19AEE1C5BD68369EEFD0DEA288D33338E78D7F9783215D5A6042F64379923573D60C85012706E578569CF07B14E6A48E823C9CBA2D54452082BDC5EB5FD11BDD769C4DFCDB06955CAB1559F95EB5B0F52178F5A31D59548DDF0BA0F3A617E865FC8DFA8C90AC15ED1FFC7869D119E2BADCB0582A88447ABCE80973ADED9DEB2DFB6E9CCC63341F54C0583966797026BD11F61D5051CD526DAFECA49B06AEE6EF2CAB3393A22A4E095CAA967327F5E57EA09B31681F0A6C02C18A171C3ECB13937C6810896CAD5E606C3408FDB1AE7A7A7C9041588772C3789671A075C6E75DA896840452C98BD8754B7BEBDBBFD2C9457BDB274F6010C265A366C7A1D105B0F52178F5A31D59548DDF0BA0F3A61DD80F93EFE8261CEF47DEF66072ADFA0C5035AE2DA56D416D9BFDF8F82FCCE1E164AB97D42603A7A0719187406FD3216FC53101E213F9AC47327637241C978475AE512BAB58FFDC1B61B363D361C03DA2A7ADE6057A013DDEE663F903D5B25874ABD7DFE15B25A944931B8A48D335677E7DE8ADD1A3BDFB07E9B4C8A71F786DE5B0F52178F5A31D59548DDF0BA0F3A616C93BF1A92B7478876BD48267CE8EC1E5B0F52178F5A31D59548DDF0BA0F3A61CC137901241434AC46AAD19EDF470B3971331C29645F2E7C637DDC7EB28864354ABD7DFE15B25A944931B8A48D33567743C32FC557519ABC4C8C5C90F258A7F90897D32AEC1EB91BE453987BFB0D96ADE180E52CF4549D0752C27EF3E5ED492F3CFE1848B1019E4C80F376242A11765638B22524E619EE4005C4FE4C0D6571FA49692E89D41587B4604352C9B4C0717CF3DA6677831B83EC31BACC85D19F66BD498C34808AC02AEC8033B95A40F7890ECD450BF13F9DCC6EA215EB0A167A98D7411035971DF9F4FDA3DB14593DC3F9A27C474C9D5815A0FFB575D7779B9F295B351F40544A4C66C524961B3C3E7AF0C24D2E75ADFA99E4765985112CB45160C990DF84F86DB775A51C0C20EC935519727ABBF5B20C57306C768DFDB524987F4234C1A78416F176C1FC6ED2DE39575A079144EC82A0278020A4834972034A9EEE72F6795DECC1A76CB2FF432D4DD66B25A58933850E097D8BD741426BC67EF0B84153C8E0A557599FA5D44019A311763988A7C37E73922A0757471BEF52B8C0FE587B6B116070E137B7C3F444FBA96F8942588CA53E29954EC6A18F24D0AE3D50B33125E4FEA5B0F1973752CC1E0BB8156F3CA33EFFF18D377E83C0655D33C435895AFD46EEAA55EC0BE894E9567B47D7D2DE8A816EB20A431EC61B1AA311BE8F2B1C0E8135E3A422E7D3372AF62B79E2F1EF75954DC101F1BF2E87D106AEA2092C4B311A95C519012D27C5004BA1E09102A7F0F7DDA87844833D947F991E1561BE22B480A097570A57544216A50917ED3A77B2BBA3140B7EC3EE4A03031CDBDA0DDF90083D988475BBF4F76B109E83D313644E33B2E5B76B98D9D9838AAED6ADAAA8B9C747F48092B5C7BF97CE9B9E7F4FA0C5857076FA21470F1E2233C69D43EC7D1BD9FB1C541DB5C9148BD3D164647232C5F004BEEFB0BA3F1B00128A434B1815147BD00A61822348EB3E3FB1083EC7BDD459CAACD236016DF3B69CDD5561B30121FDF3F8D4FC0B09711ADD854BF42A2BC64329D4E0DC1E1AF326C81A6FB8EE83A4746731CFA14B885D1376AC92EC184D62697CBBCD79D4130FFA13B0E2AC8C5781490FD0A990FAFE6DCDE96C0D279AE47BEA96FED2C4BF8821CFB03FEED5498C34808AC02AEC8033B95A40F7890ECD450BF13F9DCC6EA215EB0A167A98D7FF49DB02A17E7977BEBF2FCCEB999D7FDD80F93EFE8261CEF47DEF66072ADFA0892F05AB9C52EF597BA187677A8C8F8B1A44CDFE00EE3C48E87B61BC74F975E43BAA356C7C13F38D35B4E4FA53E6D37A4910916848DAF5D8F3CC1662D330D1E8D2AF06983C79B7D467C3AD941229E9D8E2583BEE800C9D0C1C4F74697CF6BFC2F2C4DAE3B7CB2966A56D1DE064B0CE3FAF4E779C6E735887E27F6A31BA82C53E4ABD7DFE15B25A944931B8A48D33567709A1B3821FF0C4C61A08C634D48DD040A04031707A3E82175A95E6D68E4B424DBF1586B714E432F5654A760846B0DF596ED6905F4DFF281D9607AEC42AF8E3F2B8F339A0FF7C003EADD0F46D58D80D56228969748593DF6E05A1B6C03CC3E91BD72D8F820785B5A457B2BF44480E74A59A387A77E23C212A2EEA5189A3C565D3C737C11B24F26A0FBC84F2CD94EEC34CC4BE08034AD58EFE1535FD6F32A1EAB77B9C68D417D237A2EA62C0A170470A3133C3511C6D238D1FED5FFDFB745B78963177CEF8FE908D4B42D9326673B22576A1DF589D8A78921D1C2A8A89C6F4942F68FCECD4AA7B0DF998934B7EE5B6072536A468566A60572174C563F215DA9FA450D5757C3C87424C73B63AFBC4C6AC50106F71F9BCB94E5DD2E7590F915EEBF5EA0D81DB8CB15B9EF5A5C221C0AF2847945CF25F939FE9BA9311BF3CF89BB32142ADC618F8B5C37B678AD7D3D95AD6A220EEE3F696EF784CD6E0C2A6E5E46487D2AF06983C79B7D467C3AD941229E9D8BA4167D00D2B2F03E2A24DB16DEBF145124542D7F69C51864391AA980B17C7927D34476364808BC45A0C842A49A7AB7B1D7A1B62F36D79F1A6B8915F176D9FA8E162B662B9CD0FF9203AB4086902DE90EEB37E936F856657FB7A04B84507B692DD80F93EFE8261CEF47DEF66072ADFA07EE7969AE7683C92AADF892326662AAA6ABED20462DE540B6CF0A7D8F4DDE089AFC3F7B8FE713764C127E13859A80668A3A7263672D76B941900C1345BBE3448C9232D1858CEE18B956E46EA9FB7B16ED23C3D577E3B396689553316A161A822D7EE69FB365139BEFF4C17634D729B6EDB4FD3FB0572A7FAE7814459975A0726209B859875385DB62E5E84B45BDADEDCFFBDD2498226587AD0A97E0379B6FEC7BBA9106D82F166A6D3E8FAFE3B3B1F7E3A12C32DE46CDC9F3B761CB440FCC336B997A1BD08E7FB34C44B98BEEED7B7958EC14FB29ED98D953151E362F47260C2CD04BE2ED2D9CD563FBF5C070669743EFF3B168AEEDE001ABE4BB9D6230E86780814713C95889D42144740EE33D521ABF3682F499A5CC231E09CB5482E3EB3226551767B1DD7A899E1C47E616DBAC4729FE1AF9001A123F6A2187999144D6CF17A6B7C986B025BFB1086B5A505088CD61275F17A3D727417F102A4AD2B1F87D79DCE910FC2CD36C575F33143D1907F8530A4A04B3010F9E7D1DF18AC0AAA3B8176C539F0B9EDFB5C0AA1E7CE9F6618E52091CD504B163786BD94349A46B9F58F44AC6276F63C4CFEC6F45665043D7CA2CAEDCD037E43D7B09A547A9B5D2E6A7F666283055A9B5FA04E6A13A8F9F547FE1FC1F809A42DBB7059443C9FB1FBE910E97AFDB841285E1CCA2E9FE974CAF499297045C85D59467FEF392EDBCE5375B7563A923ABDE3F8E93430907BE71187605B0F52178F5A31D59548DDF0BA0F3A61DEAB8101ED96D01E176FA19ADBE613ADD62F17C8D560E8CF2EF0C1C533CBA86AE8F774A4CE3307C4F8065D100712D65FB997A1BD08E7FB34C44B98BEEED7B79550B1204EBC9BB0E030A12488E2F56ABA659326B5351DF401CBC66D55A1F2EBAE37561E7648C56DF095962B8683289E6FB02EBC4B7D30D718B8A4B85677DC618243E7D9F44C8EEE6F036C847C7CA21EA07AF3261856EBF2E6F02C0D3AD6F0C466001168D584F92E641D14308B07515FA67F85B46363E9EA8E795771AD9211F42AB520AAE83ED7A60A34BCCEC6B98EBB05D77BA7CEA2F8D5C69B9DEBA71DEC1018164AB97D42603A7A0719187406FD32169DF703A4136A53466C4EF680EF3B1C3FDD80F93EFE8261CEF47DEF66072ADFA01D156AB733D6965B33EFC0774B4E70B26E68D72DA7B7270F72890003CC526930FB318C02285D8D02E0402BB2211C40B235CE955BF175FC56276D400D15CBFC7E1B2023A8C3C3EE7C781BBB33CF7A256850AC6768F0D1F5CC8BA97DB6270D4BCFC9EB2CA0629646C3E24322728B1D41E27F5BB1D5B7F00F03E1C290B2883F165419914B95BCAC91FCE2F6D67C561F0F21C700E3C74FCC167FD790ED747253F13EB63CBE5FE6AE782BBE6165BD294CFD06944FC1A4C5CC3E0DB9A8481485D8528690D9FD59E32749CB68BC1CCEE6DC672CB2D9B9380698F04661E0A278DE308BB3A62C33A68F66ED09E95D7ED37EA51212C761FF39FF07CA1074E4EF94378D6E62DFE08468FD6B20B7DB0D368210F5F48C0943E4C35E89390AF250169D3CB0F2CA00AD7E738BFC7889C83804EB7685B3453BAA356C7C13F38D35B4E4FA53E6D37A9F62C5892688B3F6DA6C72C17D442F4A0BAE48F3E792CB1B210022B0719F4A130211BBA8E2F26F6C29F352B6063A0E31942D0CB0FFFEB58844CC0BBAA24F871359ADFDC741F537AD656F04659791C4961C1C8B10A1A1AAC92F8705BE1E544EB85B0F52178F5A31D59548DDF0BA0F3A613FE694CB63C78984437C15F82DE65D85DD74B5E0F7AB512BCECEF0AFB9F587468C722F2C94DBC7631BBDE2D3C85C9AF0F38284F4C50AFEFCA3B594E2A5A106D3EA06716A8E450B953AAE90CD83DFA63C5B0F52178F5A31D59548DDF0BA0F3A61D53E381CF1442E2748DC2AC2919D3C53B6B9D234B01046454C6F53AD92A243372AF030E83B497BA576DA6767AAB2428273DDEAC46653026CB5E9C641151702AE00E8174E841C88EE28F353C2604FA7B70FC0C44D60350AFB7999DE88624185E923276034DC7796253D4560A0F841DFDB016BD3CDD13D6561CE0A69E415CD30CEBBA9106D82F166A6D3E8FAFE3B3B1F7E3A12C32DE46CDC9F3B761CB440FCC3365B0F52178F5A31D59548DDF0BA0F3A610E3543CD4840ADA8B7896603E2783D39E928D9919BB223FF7DC2EED56A9EB6A924E91523DF0B71F56337F1C61E2D9D9120D48C6CA5594F713B704535183807880DB60ED2FEA32964A78D91D26C505813512DCE47F9C39BFA579529609120E762A7DBE5ACD3E4E7547C51FC3C5D1F52D9EDEE6DF859F96B4C3DB8C6385DA0A4FD5B0F52178F5A31D59548DDF0BA0F3A615D0F434D5B36C0201402A9550A730D3DB1F9A78D34ECFC7733AAC4033A4494977105CFEF8BDAA379F7CD88457C5DCCADCD95DCF427051F37A01A4824913869054ABD7DFE15B25A944931B8A48D335677D0B184973D766720CC921BD9D3AD7DA0124542D7F69C51864391AA980B17C7927D34476364808BC45A0C842A49A7AB7B4ABD7DFE15B25A944931B8A48D335677C317E3E5A8F0A31EC1E20336EBCDF1E07A3084ABD06F2F799616BAA890461B111D5E409BE3720F51CE50674C5CE75F64648B420BD31B9B71507A1E4A2ABEB6E250FF55DB3711AE9BF962E7BA41C8739ED3F1FB96C62347341AC1807F45DEBA1960100825F3142BC9CB23C5DE6D5CC5D478E9D2491C6C1C9A414E5D6175D5FA0E5B0F52178F5A31D59548DDF0BA0F3A6126F652A1C2E8594F22872DD443DC84E84441A36CA09AD779FF85E85181DA9DE8BC50398EFDE8C90487488002BE1105690CE3EC5C6632E98CAB4ED73AFD7FAFEC3CFE1848B1019E4C80F376242A117656EE383AF12A2A70F0C38E9D2298FDF98536E3B295652F30153A37428C4C49218C9F05240782EBD0B97AF4ACF8233FF366B520AAE83ED7A60A34BCCEC6B98EBB05D77BA7CEA2F8D5C69B9DEBA71DEC101818C17CC66C403E2C1C212035EEF9901F195CDDD775E02245891B2011E38AC3B8E7F5DB7A1EEE624B145AAA974A76D2D6DACB16F00DB95E55939EB81597017B0134446856DCD03B2DAA5A26951E69B3AF3C8D6641EA16EC1CD7AB03C4BB6B4A1D3265F59DB1591ED51E61DB5A5D1A2F87553EADA174C3540E2D9540D4EC66D04A80D00F46646D66B3A859B159D6A50D4B5A19B45AA6353DD06BF85606A78093743DE1513AC19E8F612180371AC979C2FB02EBA99FF4153DE80E589AE2442695EDFB0C312C53D166EC2AE1D8CAF351C149AD49829054A899C200C92EB6BA747CD1103209767A86A7032AB168C2DFC59C784140E825A57EFD37501B2D29BB397A2F45DEEA614FDEA1436CDCBB5D2627175F50F1D9B7DBD8DAF7F63D3979C20528E6EC12D51F057B0C5DFF73450CA1F0A24DDC54DDD2F3B9E32019C0A5AFBB831FF99C0E0458E86D8F42D25B9F881D631C6370D0D3E59F522F6656170AE14F9F8E6DAAB9C88DFE07A6F61FACAC3EEA42A392210F06AA6CB0356254D374C28452C62542C211FC4BC31B47E5882266AD153BD7AB2265DB85D57320BBF6D59C3BD29AC4B744EB2E7D627D1806DD47477E332615693AFF192BDDAE8B775F702EACC0FAC789F6487FF9A4253BF23CAB5F7DA582E62A096C0BFBFAE46800601113BE6D19B2935E022CA71446B64094F75EA08B440982CF95BDED70FDB019C97A1B39208473FB42515FA65673E3FE7F491A73F8C112178F0942C96A4EA7B5E30FD87C11180977491AF3721A13D83890A3ADE53D753D8DD104A536A2E182965645EE362837DD1AE5F727EB45348AC939204DAC4A68E126E71E33E592CD0BD4EBF2D8331A4BBBBCFDF824206EC00D213B42C85ABDD8DAB8BDCCF2EBCE33CC9C8D20DB219A7D7CE3B57E9ADF82F20CBF65F1713D2D8D8413229567ADCD6406C402E09CE512D7C2EA5805BFDB335751A2DCBA8A00E57FA88356272C378DEBC61830C677BBA90B47361F0B0C25BD974685501B1A9F65F712006417C43123F4A48034654A69865091B79DDC82844A17CD1007CAECBA47AE34C3C682B02F5A766FA34248F7988CC0D24AC68D8565FD52F468A43D2EE000EE4192EA47D306588E0C36A568EA7A0752BF2AAE151EF528ABC3AC39CF9B6AE7A5B5DC017FE207C6B033BE57E3F321B1EF0173C7577A73C475CAF3D792E9C47E6533C7F6C5F0CB06C7CBB52EB31405E70231824F7FC0F9F64EA32802F114CF8A6B27DBE6C260201DAB6278A8FA05452F2FB0E60B1B527936DBC64F83D2A4DB65E5209D02A3C1EE4EC8B86E26852F0106D38933E3D862CA185771DE79AC31EB8034C0CDF9EA0163DB4EED20344B99E1DA0D47801D9849760DEC4BFEA8B771C5E102C66564BAC5534C7D1A43D47A7A17C7325BE732D70177BA8D4FC6232D0D6E5598C01BB493054E8F288D30D0FFD54E1B22EA4336D8F6599164F75B1D20CFE7E477EB5AA83E427D5407FDAA25349981AE48D2D3BE8707BD6FABDB620E9CF031B88FCB74F8A9723C70A401584D939F99F44DB4EDE558C86E827C8FF63E55376903651147E33BA5C0972A666B6CCE1B9C62DAA84252A1E9F880CE89946E9439B6D4B60972CCFD3E5624236858DFB874E3F53557A30AB3FB6EA7243B9B1EFCEC35EA4617D8B42BA54408832AED90683E4E22758A915D0EBB5223982F805F955FC68C2EAFDE2DD99E13A8D9E37B531053E980D81E3CB5E995D67F44398FA853E179D953E21036260B8D514379AB95625B447A42502E2D8AFC990314B504BD4E3413321686ADEA7FFE5864F8683291744A79D8003C961E701BA8DE060AED2DE23FA32C8475C3AEEC0014CF5ECB401463E4A47F06C5EC63309F1F57A2F1699D00B75525722E8BF451297D27AEEAB76782385F1E0A95051D543B4807D417E19AD2F332FFAA57F6727B801AF8F0487CA111FFC07C81F96F911AD1E75916CE6D37EEE631A6A2D8D585346703B261917C7DCFA178E55F45ECCEF116246AAF05E4A6F0527AE4FBCCDABE4287F73FB46B05849D920ADC00E611A7BF6CC4A65F1FB371ED68862CE0964DD44E81AB64EEADC571EBBD5225BE78DFFC5B65EC3B62BB55493AA0FB8796B0EE28D884F8C0E6B2DD2327B5F62D6615A28F8E2393FA185A982C15F679439B99E981BFD99A66CAEAC46FFDF2A665AE537BE34DCD020DC6C994E7CF310A57F807E209AC156A16318E2DF9B9E7114602CBC749CF5D0DA747B22B176DCA1546B774DC2785FE38C1B182BF5438807EA41B8E31159967D4C926F50F359569F521BBF17A42DE6E749617458AC223F5DFECD40D384CB447381F945D16D38E55F329FB9FB06AAD61D1F57B8BE021897CB9D539ABA6C5453FF323B5D8B26D47FA061DBD6098256F5669DB566717C2457AADB8BC487A085B5DCB1A87C2C25D743EF44FB174B66B6675F14C77FDB9B28FBAD23BF3B0DB0991F1FA1BB343063A9E8A961D3D4E47CB4C41F1CE18C4097BB71A4193186B76694A4C1D67825D2FD826D1D00711B21E51F147883BC33C19ED427878ADBDAC3BC7F59BB0E0056BAAD24E35D9C523587C235EF7E399CBDDA77D10F05F7F1C9FD34957EEB30DB6BA17BCC7DE0983C89B9AC539394740355437537666A77413C0A1F2E4B2257D66BBF948B6C3D88095AA3A2E1B3EE4A0834132ECF15756C5F19AD45059AFF07B43C3B307083AF349A1CD2048D52E2E74A0715ED7074FF74066CA5274FD226D29E8F9A5BE22CD317772FD0AE65CF74A6F671C5064D91FD3145A752DBDFA26C53521585345F5A31A1AFBF31AC2DB702F28FACA51FCD577FEC7397B2405400057B44C5A0512785377B081C75F12EFD67EF3739BF7C53D736E4CB13CE5D58EAB0A5D575588A32CBEB301BB516021DFF09E8D16EDC2E3CA5F7A766DE5AF412867F65786CBBACE0551E98A25A3ACC07EB1A3E2A08E337F72BCBFDC18225ACCE32AF7F266818DA10BBCE85BC042A76BCF5481DCEDBC9BD13F0986086EB0E741CBA5116401AA08336F73B5AAE77758A72601A03CD94600197726825C838B3B9F2045AD2D5342ED9380FC714B9F5FE9C45CE9393BDE2B3CC0FD3D77F16557BA60535432ADB5E8791C495B60A45EC042378DBF3992BD3E40AAA8BF66EA9ECF735EB67B1B2A5A5CA2CEDBE06068423D62D572255CFFD3D01A235DA5A5BDC2EC1449B3B9F3FF232CB09D384358DA197FFDB27ACA8D6003C2C261108823F383FE3DFD4EC0E295AAFE4DF8537EE883B3513AB6AF4C4AFD6C05A12EDA51C92B8FC466B478FC9B31A6C4E3B541C99881EB248DC13E6E8751B46D96ECE34F40EEB449014CD59074FFBFCEFF66591C52E4F6B04535C2F134B1197B99869C8030DFD15D84B7CAD57DF7EE134C91C3B6AA5454185348DA517A3BDAC735B33F0D2A7DE032373E52D5FC0AF626B882BAB7F2EF093DBC776E1822A7CE2EE6639B9A2F833DDBBB629237B29A2E935004D215C51D025042F886DBC5077A029B095214E8FC7854670B3600743D1F1B3594F047AC77048A1C1B2668B59C67AE95D567707C5EDC3EFC4866879E12EDF53D29BF1C183D84CADAE03318FA8277C5816658F6B425AF427C75B754EF9C38907C74EAF44912A9BE463A4D4E6458CDFFD8ED6763F25C3D9590622D4E793023EA06337F0AD985431463FFDEDFE446B26929B4A6530781BA584532E4C2BA14627C9F0B7CCE3150B4F5851E10D5F3FA9F6A42E03146A1A10A627DD92A2444C17D9BDE40E8ADC6BBE617BBB0996D315CF43AD16CB64B8FA24F1E07A0E4CCE6A1300EE436B8E3EF3279EFD142A75F131FA3279512C6ABC0F28D84A1B2C0EDEC6FFCFEAC19F5F6C94E2528883E4AF3EDF3A297E0235F47F18A17EAD1051800652B767C4BF0AFD56FBA6428B7217E764F435FEF41D7A3B621E20E0CF69221337BCAC379E44FE43FD00DD5CA5908A0B9FBDAE01783672E29CBBD1B7F276144DBA9B8B6129520B693808A9E7C76A68FFD111931284C77F0AB8418D55F91ACBA03F44593856C77C7F473417F250A2FEAAAC16D259EADB31D27171440407949B1F2912A6CAF58F9955F8FE99713491092B9479AE850A2EC7B7C5A130EE9B23A1AC56D2BEDF632B75D3424A01CF1FACC903C744212D93F044E22019106C0C662726C52DC92C8ADE5D9BA91B58F5439751ABC638E65D6939DD8ED65A947DF54BD35E4C3CD188B6288390B1421BCC92661703DA704AF78C05DC054176B9A115614525D84A05411C44B183FEBD7A860CDC09467F8E409134681460FD45FFF21A4EF4716D1546284BF8AC32F96899D76E391F3050D6643C1C32EE49BB4D0CE850A246D585032D58F9A677A614E98614AA53B7356C5B4044057ECEC7A8AAAC312676257C3B86498298E665E2EC2DF97BAB727273E63545EEE701E02035CD63253DACF7CBC08B27690D8F85A64E72076517832EA5D2B3939F118050D89A7B17AD464A615AD1459106D48EB3C2BEAD6D9BBEB1044FF296763CF5519C19BC5AD8A6E808B80BC0C14DE982A7100C77CBD08AA57E6ECC2363969FA0D03C0A70334E0D891EFED98A1B935D0ABC4ADAF5382F630796250C7AB6ED5C653A9DBE7770955BF3A03A473EC1224AF8ECA0ABF92FF07A7A8C4E91DF8684C96CA5FA6C528F61D1D5E3C2E74CE982B0C18C241CF6E18A049B477FA52E6BEE354F79CD6FB8EBCE876E01FFC8A72777D558CA88E2E3D376B7788F254BFA1672F8DEC36E35037FDB72E4761E0814C02F59098DA1976B4EF18C3C95DA30BB36C14CDFC9DD1C9775C0CC6A80CACB777271438829F4F6F87BEE68D48A875EAEB2207DC849A60BD036DD4A7EDCECAEEF5F06743754BD166F12DE4CAE05A669E5A5153E90A0448935E2C692C4485E78E6E5A73D764405812551089C87C36492A2E34738F895FD4D57DAF324F563B69DE5F373F4F723434B605FDC221B491621D0214FB9512BD584203C29DDA800DD08F107160F53659D8B755F2FC49F1FA8B2C47283985A5260BF622052D0B7920EF23F7776CC1E7D3118D07867C0BD20CA80A60D928EF0D64268F1DB2FEF8DB116D65F0B1EE7DB6D66608EAE6B9D573C964D0F69ED8674A4AA1C567D8EAE3EBC53DA2B7369E349F36EF7C4DD34AEA701F3C876FA314706C6ECD371B106CB1F1BE02483F9AC50CC8BCE7E39FF84510BFCF5A4DA44399E86EF902F3DDE79C67AF35F3BC3934AAF510307AD8B6CFF9FF5B63235D57F8903B98DA013C741C3428B56C046739B6CC0EFA0C03C5E4953D50D26C12E8E62E6F13C6639FA949723FDB6D56FCEF39FCE897D7102A8C43BFCCA4C258152B325D1EC0A59334089F7BD63F15C5BEB99068B240D7E5FE892F0597B4732C94A14B39C3C435A01D31AD8311E857FF8C47C576ED7BEB030A0264A67CBDE7C2211CE2B5CD736C6B656F314A70ED909ABC4E1C32E1B0A09827166B4E2E8835539C3EB777F63A9360066962637D660173C2BA9451FE2AF3F6F7FFF5AFF7EFE6F41D157776078119E375ED5D6C73711E3B9B387ECD8A06570AA6B6C0EDAB12775763250EC72AE936570950851D7EF303CA26EB17D55E55CAD97CD00109E80DB720971C9A8EFF7767CEBC81C68003F5282A8DAD68536831342E75C3A03CBBF48E22EDE3755F34F059B15F879A35F757505FBF08AD8655392B0D8E539F4C53DB9CCFE8138FC268F42AF408E3185FF07E8F61B1EAA6FA46924A16E65551913911C0C705D26658FF42227DF851A7404C3A0082BAC3F0504C8E8254EFEBF046C7508EECF2183430985F381F9A39FE531482A728683BD221182415FFA1E9AFB70D6708B511325BC21C623AC530E45E514F5F389CDC32CD0D2A65FB01E39AE339519D3848A47192D5BEC78E5881795B2C18037703D79A2EAB9BE5BB06474F23ADBDD42171E899BED9EC44ACCD96719262DC787F6C4CFDFA6284207502C12152DC25FA060E7C2BC90A55228C26DA74A94DD69E1DA78B97B7E72CE22D07EA33EB83FBA0F1BDC65AFC4559C9D7A4B826657FF22AA584BE89DEBE40E4FC69489A16BD98842F27E7CED00E5C7864673FA3383B5FD38353230AD205519AFECBB4EF009CB6EEAA912E7E8A73D6F0EA9E1AC743CA050EBA10115E5A1FFCF3F27E072F98134776A0D3F0BED9667BCABD9E68EB6BF4F46270833D34C4A875E1F17C4CA0F8B6615B2DBE9B2FCF1252E2A528BB5F5B63960AE4B7174C9CBD99ED1665E24446C93C549276A1A48C336D22208A7234FABF3B984574AD550C030D60DD8E2850915871093F6534D60B392667428BFE76AF04A4D34D7737405AD8274A514540925720C873A212F25D63F2B7A181BB6FE266D01000E527C5134994B99F630B81DEC3371E5B1771B745B0F369411EE1BB53422D753168B7F055413C08221EFB76A63CF09CD9167040A8B961065D8F9BD1BB75411CE7DBCE4671D812A603D8A9CF932BD070D966A69923CCB3203343F233AA3FDE52078B17F53ABFC22E73D515A63A3BE56616FC138ADD84D6E2E3AD1F1BE1DF698F8CF4E72B1E3C3ADEADCDA90FD9A2B6C424516AD28DEF9D96BA82B0835E0716B80AE3BF78D7F0B9DAB584C51C540342D89268C316931851EC580C7F6A2AB5BA05F98582E19DBE167B9DEAE57B78DFF7D4F6D322D8BC138DABCC44B4FC97FB514F2F4AD0E3BCC7FB6DD1C08638BBEE1C5AFB722B385CC7EAD522E5D78B9F02F21AA53079B499E70F5D450C58CC9BC4C79624DE65BD4BA8799089A7A32456DEA32393C6753EEE364F81A0196EC18EFAD4E21914A446EAF8CAD124F1E2A4EEB54F3B60B7A99D50D9414F488DA8F2F87ABFC79FBBE3F204A6D61870D46B3B2F4DF5ACFE088A6B4D3DD966F8A35954FE1EF07713D6BD849D64366F67711FFBE2217A177F6F28115E82BFEEB6F2F007083BB2B75A2D72526A9DAF638A94B714E4DF066744CE1619D977E20F1E490FDFD2E3976F650DC58D5D7B1052D31F35B95D7ABBE7DCD59B876AC99F0D162ABD467EDE78ADFFEA4D1ACE20E949641520FE75D5C1CF14EC21067A2B27DA8F989BD0ADD15047886AC273C7DAB8C1BA563346EE26009667414631E71B3564AAC840847A22DBAC0DA87A208CC81CC22D2E0032F62D62AB77E2299C2CB44DC9761067A9C083D4292907919C85F0E8EC9394497F2B9965C1455C0091D3AB8146A4D0664C5B24D0DC5F8FD23DEC1BF7D6D6203693D3C8F447B754C9CCDBE957863F534F69D4A1365A5A18648442CD5A53322EC1AF72287ABD92FD82B1510FD84017C0496C0C643D4E457C2FE492E2FE3F4D7A16389078FC93737B8A97D5046FC941EA9D291752DEF205A17A9761573F9FDFE232EDB3F60292A8AC3E23D873DC1A88C0712DEDD80265575AA92AF1AE787EEF161CE164B5B9DF9D7A2AF8AC605BDEEF0C11E4345C3823E86B63B7CE5D7A4B88A2E2346FD9FCA6FD90BC83E536F2765FE3A625CB4F147C834700044CF2DB7872EC8884F808FDCEE5D1D6748FE545E7ED3D8E473C4BC2EAFD4216BB7C5038072334B4F63526903802EDEFBB056B0FB76A768D785CC4CA29A206E32961ABFE55ABD5BB0DB605004F2B364B09EB48B68962F13512533EADC6FFC65EE25535426332F928D8C30499C51624825DCFE28DCC31BB6A68FBB22CD4F0967BA1B361C081AA1E9B73E8FCA6610445861BD3F0B37DC3BBB19A36E726D46207F3FAA4F1708049055926633A441FD9E624642E4586812986615477D6FCEFBD1EBB5D0E052918836CA5DFBF1AD147AD9AC297318F74F22E07F3157C4B7DD311A2F3F93D66E335BF5E2F78BC1BC8F4967C92467889D76226F5E92A6177906E7D6ECA48692AA3CD5358970E54719886BCC1C394601E8D4F439E3B8C01EC73AE2DDC576DFB57C5F5BE1A5C52257461E9F17056878B49DD4723F16FB3A9F8624E5F5A4DDAF0847E41F815A8817CBB42D606BE9A184B4059D77EE30C64DFF6A8F27A7FD2E878B70D9BA63C5398BDAFA5A3B1FC2BCBA6EF9051E12936C7B3647B2E1C48FEBF6A7CA1287472F0F4F5A274D0266B275943DD48E1FBBFB41A967DB119C1DBB9B99BB1D93B2BF55CCCF83FD17B8DBA7D1BEFF995D67ABABD7FF4B51477E651FD8E1EE7E650C6E160E8E3184F9AFA3CD2B7D293D25D831C6518F40B264849C74226EA8048C79F786379BFBF1BF97384FE6DD2324924DE2678FE5A4036F45E0B813FDAF968A523817F921AF4C94B6611C04E41BE91ACDE367FEF119742B0322AC0516A1C270E2D7831FED91776F1904C81877B74D93BFA6051F1FAD2C303A37A1B4611FDC1E57F96075B37AE6A5295BE842161115052BFECC8E9B69266455C914994822423BAD5791EDDDF4C81C05FC7458AFE17C4F6B5FC9E9A7659500F582593A34525D56D5C3966EDF25BEB2A4B0E54440643705C02E6B96381E4A21E8DD797443A5F4BCE60D31191FC6372921C2C6815562B8E7B81AE1A827A1AE2FFFC6BA7CB9F61399A91F37101C1DB157FBAEF6F20A569C2BE79608D2E426DF0929E4B9ABC8019BAA5F276B83FE05F923D3CDD9B45B229151B20E5FC011A6254B8DCA42CED3198C4B453D1C43B386106F40007C05047DC1884719D07BD9729ABE87B0B847D95845AA31AD177124EBAD08E5A935801862A7413F1241C7FCB5C24E3D204A6B982E6D86198552597C9E35CAD46CD668AA4087CDE901C6DEB630E92FBA1DBF06B5415AA776BE410400FEF562D86267ECEE07106981614EE78FDD3342E1003DB418546FA84AA682A2BCF2001B3F4D5D94707A4B4600141BFDDBE6BA9D704F331EDBE9BE3486BC5C3FDF94BEE51099989F10F08115E29E6DC8C2C6F9C06278CF8550B8E0AD0BA79BB6ADBF3BF11A883E41B54BD588298F9EE03ACE70CA38E9FAD11A403D143A34534F266CED15D32C85509D5394689D715A66305A26231E2860157B479B36AC47138EA96A75ADBDB01D115B820B310DD013B81C0CB7E2553CD2694DEC474DB5A468C260E5C21A9C2311414354F5810E6E34867D9129787E4C64AED7EC64CC556D16CA6C96C2B4264C5ED6ADE8461AF305F40793978DA2F99178EF33D7D7599423E1161D0F0959A6B5CE7248462D9A16E15C6CA67CFA9DE9D977D8FF9B24C52F991077E34DEC41767D6FE22A5B5D9DDC0DD2CAF294FB3CCE958652B6250E2A8EE1319158B38B21252B467DD5522E2D7E68F9EB94169794DD7C514A29CEEE2FF507937F62EE8FB90BCA1B911D1BA06EA1C8A1AAF598C0C81388E4FD0D2310F4AB98C56987B620F97853B02AEDC3F2CF3081D2674862D754F96D0E1FAD2796C3310D84AB76D512403BFDE5C8141C5660E2FF42D2E89DD99D3C364017C031B917694122792D91443DA5C556C2D927C53664D63B17C8EC8C63D8B45CA3D74D0B7CD9B57D7DBC591D86F001DE976764410EEBB57151C31887490DDA396B81C49B5203FA8BE424B36770A361648DE5610D24AD85FF0E8BFA76A48BDADA9D99ED220EB1F190D56A41DB7CA1684C55F9FDED8F2FD672998571954B9ED81DB3C8CD5E71DAFF453E87EBA89F3BAD615505592B4C2EAFBD5D912DD8FBFEAD94F200805064160A34111AA2C43FBE66E973D27D5CC3E0F2035EAEF6B186AC52A2512CAF788071FDEF03E348B42EBEC6263896928E498280F58B99083CA3B10A19DCD283EC94D74EA3FC2CD37AB5A4983914ECD4DDC2DC80AB8FA6A95C945A7CCE4885367939085C9E97965B160635723C2A6EBD15852CCB84763BFE22E0D87202024A824BEE0E9E164FAA0D0F473324B2597486B9E27C010C90C5D113163B0A9CF2B29C909CE0951850424BE2DD4CD21B502536C462A55ABB4A3153D0A86B7232B8CA0DA55443F1DF4BC9240F80DD34789176421AE067E556346296FCCFE47DDA106BDE6E469C9B7B88285B4376EBE4BD777C93DC16858B8C1AE51D9BB8C8603D66570B7F63885FE41A03FD0C14B908A83F8A463CB38D3E02468966F1D62A9AA76063F627E72659C0593F76212BA283BF65B84A100943B08AE7AC6BB1A718EA2D17DBE0C2C387FC43ECF7C60BABAE526EF7BAF7C3AF1DA32909AF9E575359219A96FDA6533462689C2D177D4A9C2BCBB23603387D55C70333098C529FF92ECF72E525CF43E24FDFDBD1E909EF188DF48906B2145472AF71B461FB2A7132D5CF6FAD6E109FB1A7A48F966B0CAEB6242351F6367AA96AA4C71F50DF33FAB9669CED4FC01AC733E16B46F6FA303183784F8AA9C61E679C7EC09CCC29A5BFBCB671630E14DC60D467F0C05EDD74D307FBA09CFE3B2114E9263F50DE50309BA45156D428A72B7F49DC4168CBF72D41686D6A3F4943917F46787B879071E6C00BF2160E44EC5505A9DE52862786F7B80C2553200013F3211C3D936D675566AD37148AB96B62CFB40EB928D4385CAFDA3AE87183539DCC366697ED0F04C2FEEE86BDA8D256935CA0DDE2E30D26C91FA92216928B1E2896FF29D8EADE611DD5F21EEA0D6B6F7A57DCCBE56C51A74F61E8FD242917EADD4149290E9ADA2361845C4BCD4814D0245BE4CC17B84F4D6C70ED07C2C579D08B782B6D0D68BF460D3214E320FCF4777F5B21DECDBC2FAF9E0F5087F7A683BED41273C21561F4C2D1D7C7D2053D168899B94EA83AD51BD706956B1D6685BC6317C32C26960980B9FFF3D2131F691D7A70113C23F82F61A4BA74F06068DD609C0D64E38DB0D279693E8131ACCD8F1F185C4EB988067DCB4AB4755030FB552A25E294EA9EDFC2EB29662AADC5172231EFA9F928022023582AADB16A57BB182806D6190997217B1120F1F0425BAB2273C4EE65B666283055A9B5FA04E6A13A8F9F547FEE7DE8ADD1A3BDFB07E9B4C8A71F786DE7CCB74B39FD5F31AD5733F0281B448EF7F8B6F643176623C532348D0923DE10C23C3D9C05BC6D40F3A25A6D0B10456D2E93677C783E525BC5E4D4E72A041A02A65E9A5F32FFB69B9CF3EBE13CF4A0CE9BF05C0BB49675172843C61905D28AE89ADBD2AB587BA15695AB7011B230FE0A5A33DA46A3DE53F838C0D9F98283978A2066A350788D5DF3592E92D87FCBC9799C439E32FE0F467B0C49E8B06661805D117908BE3A2502958E3CF4F31DB1EEA12F93CD0303E9B69479986EC54309FC84831DCF9F71850796E6F02D733E52000DB469D00D8F3C9C77B37BD9626693683D97B4E4D21213EFB93A4C48305063B03C574C76E79AE443CCAE87961970E6FF9AB389C54FC8A3016A273237BC5D45720B7D82651F8A6148A28BB931FFE32D3CFE9FD0C95E1CEB614820857BA3AEA8693CC976AA7AFCDDA684DDFC6C1FD08165159A3A54D1E6C784CE7B1D8EA359F2175EB9AF696EDEE12172448CF3248566FC65731B335F97F81032BB658BC486D9B7D598025E8B45F5C70D00DB2D66465C54D1A16A5C49560622C851308526C0EFDC116205C39C6310B0912C5E179AB6DDDA6721D33F11218C5AC587D038336DDA3CC8325C8E0912AAE814AC734AADD65964A0BABF81F7E98ABAEA8DFF2D080490668C123A5F92425252D9E7FDFFAA91B86A9B6700999DF83469793E5A3955C16555B7FB133E7F6982BD53FD7FB293FC5AF3F89F92317705480A6C8F881FED1CD1FE1622DA6097F302AE13D95D3352461A7BDFCEF892EAEA58D7768C99D675871ADA78A46BB558B34BC7442ADF5E72878F7F39B124FE510167EBD74E95FF1BA1AFC4E71CD98B96987AB1318B1FB5551ED295D6614287156BFD3E153E01688DAB135CE6370064664B8265E604020CE973DB77D2AC4462237371A0893D8A7A3D188A2F226B57E6411B4720474986A7A60F01AE0BBBCCE9BAD9DF6B0580F211AB3919247589A14D4BBF245F5D84D8145B20C31B030C491B8814007DA2ADD59E84FF5FFE027E54A683C509C8A9A5F8B3527D2AD6A5EDAAE349041A369AFCB7DE463A668C8F6D4CCCE7D09770E39E61959B6C21F543B416BF354B802D432F364CD40340BB14B4EEC95F0930D156BB99A47C2F5838FC871387051BD93B1973E375A84090A0279BEB6B476F26C47DE1171A3AE91E77039BFD9BA1EFD79CE655DB6A6ADA3465131D28523C10B0B345E982096EAE1B390587EFBEC4735C5D6B28DD12B45824B13EB2A26D4BCF134A594E46C3E899D94312554DD97D87BAA1D89B7492798FFB9234D2C92BE548C82FABD61F381EB69B97C5C7B1CFB9CD4BDF9B15B6186D4C6C71A53C7AE533F0425773138C8617CA9A49399F33F4C799E2797FFAF07A1710ABA2ED3ADDD848218825634D3FD38DD2F68B6BB3A1F3BDC6312FB890FB3033D028E6621013F7A0E53FD5B21A62D99D39AD3386BC8AD9E4A97D8A7CC6E3E735506ABA84705AAB1E668A63CE3D330E4AE4583926EF3ECC5B9C02DBD11E3948051D7B35E7D0B29DA21655D336D7A24D5E8BD81C12C927B43653AEF54F6C21EC6015D2C440E5175AD2B44F3CD493B853D91790C8887E50175B2D15169D34FED5BD5249F6F4975FF87488126DB51BD212A404373C7959715947E365C911DAE00F81FDE7498C7AA27BEE03B89725E9B9F57AACC33F575E1B6ABC470AE9F089BA2622A0D9D33311D55AEA0BBE4783E95DD5633F2DF8B1A8A8AA5B85A736F51635830A6C72D66FA2D9A7EDEA0E0B114A2E5085025198D3C09E7DD414CC63EB742E7F79A716CF1E86CAE5C7174778343EC56A5B96D9CDD32E2A5F0B072D799B77008C1FE51C06848ABFEFB3ECD360AA6B00F4C16261F1BC713EB0EEF6173E3090FDBE444A2414B259BB93B16163258C1C5905181B09C7229C65080E4E1C54C94E208CF5A96DF2FFB1ADCDD95A76C83DE4CA2CEB066FF2677A46C3FD70DB72C4ED1F8AF78A58AE0DCB7F5BC46B8CDF1C279B7894D4548ACBBA6367B190B9B1ED65048790A8B81A1C18E3D6E16D9BA6A8B435DD6C523034E72F410B5DC600A82AF2A6F9D51FE23A7912D3221D320CD6E557A9B195AFD8AD81ABA2012F3E3BBEB6FC5C2871E53DBD8DCD708092E1BF7C1F85D4A6C759B3F85BD6854EEBB03865AC1A6C5D659E34078BA0FD85FF71BD2F40059B955FFE075B69D875CED443C8A0E16A1D3ED8C21684A2A7BA78A99F00CF3CD1A9362AC16C6B6D8D5489ECD4D0EF02B645901C9A7B93B43D28523C10B0B345E982096EAE1B390587EFBEC4735C5D6B28DD12B45824B13EB2A26D4BCF134A594E46C3E899D94312581488CA1CDECE76006A0DA2BE63059BA0C98D76B2DD92957C6F6C780C25A3DCAEE4E78A5C7F53F79D92329D76D6BAFEEA4579FB9D4E57DE35D4A84CD50C982AF89CBD30512E4C04E9587BB6F8FFCD78D290FDCFFF1F1F7C11E0476175A5200CA59E75EDB8DDAB8D47E372995D6E1AF200648BA22E2D995C79D9FB32FBB0EA94FA66CA231EAA20106C625B77798256EC470F98A78773760038ED39AB71B19D5DB3EFD3B77E206A5B95C4E9CD12C5D5F696B7FC7CFACAF4495982232F8F94B2969F0A774B67FE1CCB5BE470D7C156D0350318FBAAD273FE5AC8DE1AA20F43438B6A3B408DF01072694CEF830025623E304AF3B62E1C48120E144407E7221035D32F7BFD5E3508455538DA1D12E0EB2344BD5DAC76110ED53961A65AD381BC365EFC785EEF542B91B40C685DE0A0580AA9A7394FE39D1DA3D0CFB207875F4408E851EE361BEBD533627DDF4657B10FCD25737B608E27B0C2D70924E596AAFA5596C2165C1CF2CF536A2C071CDFFF3A1F44CE51861294690272B9D7829A99A9C3C918AE2BA194EC567F088AF2948A2DC2A3EEFB95D3B2D7EECFE96C14087A55A3C21234D35F7606016CA79CD65A767E42646C31D91786A3F6A6073DA31393C64529453B930010D0731087F99DA4228D626D2789E371A9812F12397F35A9BD01759AA533DDC1198E07FC8FB00DF6CD9D7AFA85086FDC9515CA5CE5C1FF2411585C15CA3B03C4E7EA3B3276EC6768DA77F460E5489265C3C023DA7B3C992FE08F90CA38C4F6C058B09BFC3EBAD4689D0BB5FC5EF395BD8204C8447D3B993A137B0A05E9800F97CC7AA290D4D519EF8D7221B7D44850714142BFCFBC2EA44D35E942524C981763076086D3C457745B5F4A73D6740B8F7AA92CCB5A5809DC411B50FF0E7E3DA8775BEC7CD683F4FCEB2300D09265E5387E67EC193B8D4DCB33C5A0F89575B9E54DDC49845A38F4BCE0125EF1AF735C38448C9C4FAB3D92F80137094A7B0F92BE205C6BBBC9816E1E9BB1E6B500AA377A91EE3FAE7CD4ADBE13AEAC7101F65AB03920B471C451904C8B6BFE41FD5EF395BD8204C8447D3B993A137B0A05E9800F97CC7AA290D4D519EF8D7221B7D46A0B1C2B89D0CC160D61784E98A2C1AC981763076086D3C457745B5F4A73D67185327668E388C1CFA1F5E9B5605FF3A4555E75EBC3ACC2034F97F17D7972692D5DAEDB47CD4E91B3E34E055CEED26A6633D0F0A1CA9D3081B65AED250C648128B299FD97AFED5087B52DC541C38D5556713333168845DEC8BA4B19DA49857904FCE7E3776D73CFBAE75F584289BBEA2179B9F21B46D1088AE2E36E2C7AF474BE103B591DB11D01EDD54B71527C661A7084AA9098E7F9134D256791F9FC5F649C8CAA30A2A640D63975FE3031F6092666D05981C85415ADF569AF793F147AD7DD2C54EC1245BCC2BF127D2BB95B1694FBCEC3FEE1CFF277FA034FB3398ECA4329447E00D6286DA0645CE08319CF8C83C595BEBD034FAF7B37C04CEC3DDB8BD74EB3ABCD78425C0518B004D1B650DE65E64AC1315B983A64F6EF560CB48A49286DAE9BFA28FC8BB1C84DB12A6D1B0188DF6CEF0AA558731D53BF82607C82014747EDAE6DF11D6AD59037FE7F2C9718BC9CB5DB73555086A93EB9CD5DBF867090AC107966DBB61BECA17184A4E8D0191AC4A665AD1FF7413A4C07D72A0E28712A86A7AD3DE6E3EA5CD42D6200CEC38E3D92D1C6B6C101B620BE98DBD64685E7337771974746EBC25CF6F0BC2B447689D6C25E140425A7CFC81C29B6864EFC0FCA8A228393446DB215F975917118BB850BF09F5B69F6EF0AA475A5AF36D29415DA0CA7DDABC9DD77532CD72ED31436CD3A25B6CBEBF886E75BB545313772BB84D969E740331149AF9DD0CD2178A97C1EA7B49F9ED3423BF220E2E232F5A95495C9D135F399F6F35A1EDA6E2A187FF427B92D650B0517C90D8BD0E8D2B1C9C27AD2156917CD7A6CEE705742BC44142B8553BC7F59E5C8D0365EBB8BFAFF6B9486DFEBB6DFEE586C14CD04DC913110CAA15BF8FC1B21098AAF5A52BD10BAB0BFA34564BAD68B5569BBE811907895657042DE014C02F79A07C93440C2D1A0BEF048FB5D470F858E79F3115CAA7E4C9F59E7D7486BFB1BF8EF2EF264F9BE77FCC8F41F5B803C2A70B80E6A7565F9D3B1123137BF6A27E8FED2D5EA5DD86EDC8CED518571E00B679A0F5909CC12A88D8F16D5C10623B572ADB922D7665D1868E309E747CB1A9F948439352ACB73262D29FD03FBDDB9B287F83B1BD9BD2E63BB180887BEFE255BD185D4488F4643AE682F5DE1B518E018AEF407D1AE64F03F91127F1CB92381B3B02A511C5853A9AAAD2DCB59B1BCEF314E1AF5719B5F28789AB75A4DD67512D446F4205D121903FCC086EC0A2C4BCF650C9A52C3A95F21E43415D231FB0B3693B1DCCC34B85B83C7AC395429AD6F752D9919CE9BE8164B5659A6F9D6E56F5437A2E93AD7223D9FDE9AB90855E8CCC0EE28C1F2107B295FFED3A96D35D1D8B7F2433EF91F62E7F585B9ED1D60AEC14941D21723E7EDFDDB46F923E9DAA08061357F371498C531E0562104CF007C68A770A51B6FC61DBAA3CD81F1FC7F99E579FCB6DE1862E72C4AA12FAFF71B3AB248D2B1FE10325FD4AA8B63BB537B08CFB70CE8E350B10535ECDD41DFB2557014AB0FDF8555131E27F73C6E0FAF3A5BAA1743B65B8F48CB063AD55C78BFA843A105360C9723693E8879A7C52AFF19F6E6925FC33BE1FD55A067E69998D396C89E151172B9BB13A88A4452090EC222483E969C2DA200B207F307B375532EECBAEF7E95C62BD28FAA5AD0B52643586F46E0CE72F17BD318768490FB55C3054AF111485C375895D6E7986347BC95DABF00A18470374F646FDBB46E0F1E3C1B4500B41CB7AEA5A2CF3DD5D24F613C341922A741D0041D647BEC77DE5A2C9DCDF8521D9171123737621FBDC7FE810F1E2FFDD7223A07F61977D3424667435361FA15A6FCD0B7B6F7D140A977D7268D77D3E8D8D2A55D0F10739ABD4851B0637A350550F6B893627D592BCA6796010586753DBF9FE729B8D67CC769961AC127216DEF591DAD59764050F5DB6B55E151DF2B7D748D7F27677FDA8782659D536CCBD790C700B143066A932E5F6CC30D027077B7501A2B3C5D77AE79B9D78E685266295F5E106C0EE76ADEA857B04B5DD6EE37897540A34FF40A9BE08FD4523576155D02484BC8E08717A6C14C6EEFDF01B9587805B92E44F99363BAB198549 \ No newline at end of file +22DAA16367B92CC030386164898346DD1C0609E5E4216F8DBCAECCF35EF70F55C25CE8F59EEED9164FDD8C3D453708E101E456346123448D658C94C0869AB7674CE7EFBD6258F1FEC412F8941F11017D143F2C4CF0FCBC32A3002C132208834E3C52CBACA4AED32A44BD9B515936CC0394704099B511F18BF3F35BCDBDD1A76E49A45DD5DA51ADB54014B3284BA7A5BB9A69A60E35966EE12ACFCD5D4AC4EC96CFB44F8B15BEA6CEC221FF7B90DA9FC027927A6505257C3E562934F81FCF81CF6ED36E981BE2A608F5B01B6138500D16C720B560EAD4D223A280E54FCE22838AD070DD8219D1D5FC6D6AD204C5E584B49F419C954E944CD189340FC87B01EE424399AA4ED45AAF0B35E10D9B36BA9B493951BEC257025998ACC0C8115CCED73BFCBDC1FFD3DFD6DAFB1A065DDF8B7CCED61C73FFCC02076BA49FF37719AC60E60F11A75716A0BD6AB221A413F0E80A7A8F58C670B5ADFA7A914CB105EB8364CBF5763D2A8BF14072D906D715FC779F36987910C29832E56A9573762ACB105EFEF5119892059422CD79300EF60408F05A1DB8AD64E6B53C76AB9A82BA2DB9F266EE5ED7C00401B63AF4709C71C16D11E0E451D79F96CDC0F5A9379988B6413C9F6B41A0343DA3869AE33A69312BE6DF05CD5BDA8783AE53E3843A45A25A4A4C2FFAFA48285F419EA9909B3B43A89C53CC5F5F58EF747023111CBA085BF16F8C48A46FDCCF1324F2160C433AC7092ED6966E7B84D49C2809F015A45A2B2F8326C0066A247F9A630D74BAEB068918CF7FA09EEA004412A9314D6078C4157C566523EFFC85678C063A36FDAA9A189FAACB6CCDA183D4DE30F4094CEF3CC9613D5596017206BCCD7D9EFFB34203B7C3E60F33E96D5A288E494E030C79E81CD6698C494AEE621467FCC615DF4B4CB587BC4BD594EA26668C06FEB662676C5110D7A14D90F8D1B0921964E6F48BC738B160F3AE0658CB9487DDC904BBC7CD80451975FDCBBBF5CB59F7DFBF034F8B738375A99D1416696BEAB17C924E5D2D37B0FE5C116FABDACB5C99F245C867A96D21792FF7C5622CCC88C2EA0BE56B3DF069731B22C9116DA6A9D75AA8CA50E9555FE32EC237A48A5364F3E09E5D63961EEBF795139CAD4D79810EEA914B014D0A05E4D9CAF883EF7D94E2432FAA0B657FF9B71049D7EA0959096B941DC18792A1746ECBF91F5837728DD7DF365E7D168FA39C61DC65F7351A35D7172E55F10F03197686ED6AF14D8C5AEB941A35DAD514D58D84C3D920DA793D5CFEE71C25E53EC21C1936FCE766119A6492CBB9B67925B9DB30B75E2391D8DF684AD5DF08B64F3DDFC31FEAAF35B5CA72BB73BCA95CA621C9D0C03E877B115EF2B3988078E83AF83D2AC691092C7AAF8D45557CF4003D4FA67A81C880EBCD8318B37C5219808335CB7F8664E176769B1BACCAB58E0E1C8B2F7B06D339FB38718653D352F6A5B2FBEDF758F2AD54B2548DE7A343B23B8E7B437C1AE212CF0DE693DD84ECB9D922B756FCBF8F67C143A90671A7A0DFE8A08063F24539FCD1579DAAC2A6DF8BA36B6DC901FF6AAA05763A10334ADF0381DF233A56FD68CE17F5B3279C1F5CAB7CB1D8FB5C490DD23B77D895061426287D96106858325AA4E666605D6A1488781190781DE82AEF9EFD0700D189757D64634844EE0EB21F152401DA3527A75B29519B9115B9A5CA3F2C181551079205A874877E61BCF897C2444DAE41DDC644D8F2635211C6A1851AF13DAFDE63DD929ED87434B8C2E3BC0AF17040ABC43EEE2F7170680AD7194194EA04AA55905F746778DB544F9F06013E3276BF535FE4255383F31BDE7F5F9CC241A7EE71CC839F57C6A8356B89BEF0C43975A1381FAA09D7CB1C0ACC85FDFACE418B994FA2A86E0F4B55E17E40830FF0236F140455E44063D126F164DAEC12BA124D2D212D52311103353E5D7E6BFCA89923F294673BD43CD5DE58C051BE48F7CBB49687F675A4EE1A407738713130868401CF272324A3675A1DDE2960FFDA9065B1E5479E0B62B5E36C8440FE50C2AAF5EDF7FE1001869A9A93763B9B805B2628E6759A1DBD1A68465709D52B808701E5ACB87E68AE661BE8B3CED65D6D57D23F3680E21C2A3766D0A13AEE06E042C973A04A1D13AB4E320AE59DBDCCE0A5DE7B3E6B6D70DCA38910B3267F21CFC6D5457B9C119E1AEA4CE2DEEBDFBBAB3731FFF612426DF576D4A82AC5B2C043346B152E1632635C708D6BCD21902666EA42CDF002D526D91D37576197FDE6721211C47EED3F1D753219E8730EF4299D321AEBA5115C4C99DD532B34044CC1C2E65D4421BB4F28B9A10A0FB6B1D23B1C1867B698C9DBEE0600FB29AEE4D5661D128BA572B285AD7E646F689D93CC5C1F41DF28CA28A402BA3036745A6FE8C783E4E5104CBFCA723F28FE4377A5C9398592BE67BB2F5E8203C76DE5197B39B1477DF3FE167E667B77D6A965F98B2CB6AA37C8AE5707AA27B3D6367277EF6D4F90DF1E60929189CBD8215AB3510D1A62935D672D7DFC2BA16E204B77BD2E8BF34FFD6AB21A87D147349F58BD8F9245B8B396E0DFCF23DB0DDEE7A32DFAEA6E1ECF18DDC32E868E1C2A54CABCFE97D08CAC8856F9353A21E3E840AF5DD56450F474F1AFFA6A4AA5538B903C2B696618BEBD087612F0800B22A721993A7285F462F30CA340A093A37E70F49FCA876A3096C23A2E08DB4619B5C48DB7F3FEAC8DEBD60642424511DC26DCE6B749FFF58C3905D0E095768771EF820E0944BCD2DE87F551E388DAE0CC5E81653CC9F82411E6B84B358B6F2FCF3933A356AEB2E799163E163C6A7D79FBAD027291C77D630A652270F10ED4DC9F7F6AF04FD21FC7257C6079DF692170E0065674323313911BE264C40A0070BDD9E631C5893070134DAD54D53C9A47694B3F731AD6A6D45D9661A9A5A0C89614352199E3E38911D7649D40ADC731DBF8B100644BB3D836CD15A534CE876D98E92810E0A22FC410F6CB55D224689E2C7FC6C6A357D2143105CAD937916EBBE2B2F683237566EECE0CA25A2FC51283E43C0DE5A9875BD13C94E3EE9FF71B77E5A410CECF084565F535DDAC9D1023BAF6F43D3850FC17E916B277477FA144978694FF61852C77805C28D29C8A19AF52CF3C0666C324AF9D77034C1FD1581179C063C0B9AC1D72A038F4B85214B2226ADF8702B940EC21F6F5C25A432E317BEFBDCBD735D60F8DBC1AB833B969E351C113114E5AEC7982BAC7F4B095C77EEBE42FBE837426409DAC0EA79589CB07B0437AEDF524D14BAF59A3DCBC8D4BF2B1C4F45C6F1B9D8C76427D1E242DF18A4AE933A8A3A4CED486BD0EA9277E093D36463C61E0DDE2CF5BA7E103689FBF7184F547BECD5AD25C635FA921FAC0ACC9903B448812BBDF67DCE05C28D29C8A19AF52CF3C0666C324AF9EDA4202C51A8100878F0259D6E78D637545421AF73DF114174D1B0CDAA710C0D4671D9936E9CD93307F8F879CB2CF3C50A1A7BC177FD4D38ADF97ACB09576F2BD91EF1D4A4244F665BD0969D372749A305C28D29C8A19AF52CF3C0666C324AF923815C408A0E8F777CD2583FE2062F438A7682D6690478D1BED2315E3F00E866C1AB833B969E351C113114E5AEC7982BF0730EF2A4111EA27B25DAD22F3FB483820B695209A37DDFC70561A7EF86EDD22EF31B834BF01F50873B6913E72AB018D5093F092F2C2BCD802D2B91EF5E179416255AE46B97E9145579367068007662EEF1ACFB3BFB7B5E448FFB764115BE3141FF35528F85373C71167B13AD82167895F6029FE858CD17B9B43029811056962059891A700283696F8175F1D805F14855A406C54CF4749D4E2BD5C00F782BB870946FBAFE98A4F2DA1EC3F4F1016FD105C28D29C8A19AF52CF3C0666C324AF902FD756803F2B47F0C54594198D273D6E2BEB8A2CCBD33215C84EDC6A48412AD9219952C8FBAE7D669357BC7B422785F41FF35528F85373C71167B13AD821678DE1AEDC5C49478E0D029291F3A98D315825CBEC7A61D64012300CD34FE07C5CA54BF1E91E1D1C6310035B73DA20D0D9F05C28D29C8A19AF52CF3C0666C324AF9C11E23C1D743CBD139E1E1F0459D4E4A0B58B7D69D72AA79325628E1B31F394F05C28D29C8A19AF52CF3C0666C324AF9B9EE558BCD2C3970430837EC85D734B87F95E78BF6A283BA9988B521A47A41BDD9C0EC00939DEE2574F7875B3B098A408873C10ECE16421EB807A62B13FCAE375BB74D628AECA3BD9C19C2A8D50946E805C28D29C8A19AF52CF3C0666C324AF9FD3CE85280A2D758C01B7D8CE889B8C24991041F9FEAAC90A271E9DB4D0BED2958E3028B6D30B2014121B7897A48A428E06B5A60EDFE80A70E8B1222310C7CFC1A639AE85B45F3836BB04BAB585541EBA80FC5AC5FB7FA13C70EB0D1CA40190FB5F8FE78C8D283EE9CF7E26ED287E1B27E90D85B3C77C0FCC49FE301727799C5E626F6BD4395121CEE9D11BD9160BF2201EA2D833D9F9150418E77D3A3B4F860505443C633C4EE6C4CBF3709FB8FCC64F400E3A9B3F97F282FB88C60808D00293C1F733615FDAAA5C180D12C073A8412BBD380BB60DC4773AC037BBEB78103C8121F28FE4C8E17F6C6F4B19A7DC5B9B5A189FAACB6CCDA183D4DE30F4094CEF3587A484338B82B7DD143C594401E4D0DF7FD608DB622A03F3C0EF94269EB2C7E93CB72F3764EA83AFEB2E062C34D2354BA63582E8187F1487390D031EAF2C8EBE6415815F5ECD7C4E72FBE4228B3E12F635136D3BCCA82845D49649510BB90BA43A333792275C86A0372ED608A6E22882FBCA2C83A2F7ABD0DAA21D443EE0BCFD4722C78C61A06445CCA2807FF3130A291AE10029A084CFE86851602EBFD2D1BE17240295A7E69C1DDA7BB48462DC9F3B19066037BA4316A1FF10788AB670D604FA812C6110E0C68D4B6BBA93A6A95D7F098755DBB6CF7E2CB170A3F6B271C5515514FB01789F488B28BEB235BE05CDA8D83D971DB00CF7A845EE904833D261E41FF35528F85373C71167B13AD8216787D57B4BA5CBB54BC268E0E20ABE595AE56F2387DA935EB666F3D77C59FA73CBBEA676F58A843E809AD48AC102EE1DB12A206898ED94D69EF0D868FDF7355E993862D80DC04D43382510D88042A0555CA259A39CAF911836214412D0C49A0E5AAD65666C9BC11F34999A4BA5902BF243C56F2387DA935EB666F3D77C59FA73CBB826FCD5378B557CBC1EBF7C22EB8631896C695C97340A74AB3740075489901A94722E419647BBD294C83945AE9EBB1FF5501AF1AC28CA9F579D326D8BE740DFB686F6F8EC98D1E5B61EC1123698B323DC0EA79589CB07B0437AEDF524D14BAF5545C9BCFF3DB20040F337F1F3906CD73CB78210273B70CC470466232637EE18E5E6AAE9AD4359D929AC271390946C40530B78BC343E2FFEE8A800D6F977C4056D2D37E4D6435E6A379CC5D16789CEC38097DC23581CDFA72EA11715CF62460D2D0DD57862A8897B5BA6D4F865FF0C7CE155CB1B0940975ED691FF19D416975AA26BD2A8FAF6D3BF47B4A005CD37F9C67A5E3D42D6F12CEE01091123478F0FED450BA1A701C48D9DF1D2C7088230F6BE5C8A4C1D328CF4CAF9B1B4208F8D295ECB44E688B0A2A646B2A1B815602DBD3EFFADE9A221E638E8515F390BD45EF8EFC0CB5D4C724E34BE62176CBAD3B55BAE0C40EC1CEFB0AEDF4F020CEFFF037BBAF92FEE5FDA909FB5F3351B903D965D6A45D9816F1139D03D9B9B53B69FAD5A31FDDC0666F1C85261F319EEFCA4D133CAFBFE328F8D948E781D417768D73F4EF360A4E5231E1C0881E56399787A22C2F68E27C6E3512E8D648B6D80ED3DB9166F41459DB9CB42BB93B94E626E3D2265C43E37FA3BB1FB8FEC735906EE68269E6F62D80AC7470E0B37B370AEBB2D49A4873E985EE3FECCCB41DBB671215B494FF18FE4EAA26A773012EF68EE008312BF91670BF13F16911D60DEE8AD0322286C713CFBE728A7FADC8C9381B8538018D173BE01CCA64D3E40645572AFF0F752AAF9F9659382845A813E9D4B9BFDA2D4B16D2E24332F42FCE55C031F02ECFFAC89B6AA504B445AD91C0709DC904A1530B2D7375226D33C653C73A18C7D752BA298969EBCD743654E9CC95C0A937E256F24D36148E9D70FA86C2C01CED746800DB5CA1B54A6F8D5892E1C270732993632595921DE2663DC0A230CCC13B4DE3312F941857E28E162653A9970AE066AF1F596122DBBDBFB30819FE0EC4A2C71E74CF86B3AE9F11A4162F96AEC0BF88D79A2A2E9D049C1F290EE19169E42E461C32F3D48DE379AF02366B794D540CEF1A6E3896492BAEA61CB5032811D9D0DD1FC788D2056093F3E14D5B1CD6CA96C7543F8D80E19E4C467306743F21A7D7D2C18DFC2DDEDE608F9E1DB7C4AC7CD6FE94A3C64C24E17240295A7E69C1DDA7BB48462DC9F3B19066037BA4316A1FF10788AB670D60C3DF3306F19F62A69D88778E3EEB1A55C83404C7B4F1157290630B5A5A6AD34BBE48F26AE5115FC5842736DC21532D402EEA945DE13F572031A713FEE8E3D47CAA36F7B05174FF2D631FFAAED61D4E56A4BB744185C2F984E76570E7DAD0C237F30B15B68A590B5BC9697A257A7F7EA1006E6D266E3754859E3795529DF707AF3617E0A47399AE2DB893FF654E1253277FC916C5FFAB6111CDBFEE42BE653FAB9B78EDBA81BD1F48A9203788E42D1BEB781B84292D84455D1D17611E6D910C1389EED1588D9EAEA076ED82F2151714C92D7C04F94AC6FC18146CA1D3F994CC7AB79DA78175FB9DADE105FFB7AB95A2054286EF4C678568C78461AB5D51B4417F787C8DFB3ABC1E8A3CF0AD326DCC7AB3EE029463C9FBC16EFDD9017813901A39ECAC0C74E271B71E42660BF576A264245B3F4377D43C9098D14931988DD6B6823362A524DA3F8A0D6AA52D7D1558FB31536876B8E507E34E01F7AC9BA1743A8DCB91E2D46D1886067EDACE62F948771B226DA87F5FC43CEA2E8290108C3B5BBF64B83285E79295D88A1F304A380BAC17300FB2FD64E1FE0CE92BE4CB18715E9FC0EEB2EFFDA222433188E99B05CEFD251F92CBDF22E35C7EDF719ED0D6BE20D6C0EA79589CB07B0437AEDF524D14BAF5CE226292D40B24F01CB97C7712832F9729F02DEBA2C6FC6C0A226DD6D6CAFE160682713ADBB2E18FE4F8906C6F8B768A88B58AA4259142AED2333AE73650E773BEC40015B91171B1B4BF9B8C68686C647BDFC2B4AA6596AF36D882FC3464D6DD6FEB6ADD5BF224ACCAF68D2E341BE4F041FF35528F85373C71167B13AD821678839FA87F83B69C43DFCE83C4CAF2363519BE2624D4E5842393EFF18C8037383A84E2231B6D8F27B045B05DCF0EB63ABE8BF5EBFA3D338B22261D067A93A3788DFAA3EA2E7E0AEFDABF5688CCD0CCD0CD91A99CC73FE6AC204988E24A3B04833083D8AAFCAE69DB47846B1CE94908CDC97938DB809BD048C42A7C658F79A1934683252CCC8BCC788E65B6D4193D146DE58C0B34DFF1C76B4FE156845B0B813FE2D236FA51F75C464985542B9ACBE0028DF379158CA32475A832BD2CCDF52C3062B373A8F1886BC03AB1A094DD4B6F27E7963D71503922CE66A690501DEE9BD3367CC60FD3E30978829A3984400CE1AE34EEF8CD9EC26A0156E18A178835C6832154195F1472B7F22741067B06F04977491B80CB2C5860F0E378BF71A9AE4B4A0E740FD06E960762AAE6D40029E471A4079837A27733314C53A43FF2D09C81CEAFE05B9C8C503F854AC91A08D2E69F30945FE450867D1838A593A118163576A28303DF9B1B530BE2CB3B00F56C38F4B62E3C3289C6AB4C1BDFE060318CC46CFDB5CACAFF5619000C9FDD8922D513366BEBBA2A4CD70DE94582FE2FCF63EDB67AFB3289F1ADE014A195CDEB1E8567B2B68FA7CF291DE2B654DA293C98F6153E68037FC5071BF0638FAF5E4F840ABB09884238973DB688602C293D9F34D93996FBD26757C352E58DB8BDD9611AF68206B58C6F051C8705C63A7D84DB01D67CBCAF2475464A6A2627F7CC9FD0DA332C5B3E94E22497DC844432857CC5897F887585AD4F31FE8589766FF04B0727331E6083B806358790AE1F73B7047E5A7841A20693B384885CC142AD514C525256BE613C81922C38649DB4D8549E36A1480A56098BB86BAF4D2DBAF5B822624B0F8971D96C9605176997D8E5BBF1A50B35002A949FEAD7DDA87F829357FAA35839D66F45BBF9D8E8037F7EC7CEFC5A18D3ACFCFA94473A78DE0BF2001A7DA4183F150AD0D83C818FF5209EA012ABB739F60DB45A475962260BDD0B104C571FF651B3C1F11A8A08063F24539FCD1579DAAC2A6DF8BA36B6DC901FF6AAA05763A10334ADF0385E56C949B1B206ABFBF60262FAB9102B05C28D29C8A19AF52CF3C0666C324AF9B1F2A113F06D7604992431034279DAF7753FA6773CFE21D73B9E92A71EF550CC87AB3605FE7814973B70D8CE3CAC6F6EE863FB281EDC96577EBF427359A2D830E6ADFD29D0D88B3A35000DCEC23F09E37F6A7AFBDA97DD8330204EBAAF12D7171A9F69E8FD6C892880BF6B4DD8ECAE16B5A5D8A7A199200C96C845E979332EB08CC1FA5E47BB51E37B997167ADB099CFA2F5D29DB3E9EB3B5108F077A9FB201746569D8739F572E393B2540CE575EDC8B4C6F63370EDF14C2358EA5C4B093D0E0772CECA542DF9C788BA436D257E27531715DD6A51AF22FAF0106700C6AA25B7C7F70B246C1A0B1F1DD0E52FAA3F6CB399BA5EB3C2E2ECB93839359980000E4774E93436950CEB9A63D50D9456D2C7ABB517904BAB1AC82DFC3DF59A368F326C206EA092B7B0082446391CBD569B27B2045D8CB3A893F585DD6C388D8F42FA956D0D58184FA0C49524FB3FB5DE394EE84D8C8E43111C101B5AD062C1B32E4C64A7CF291DE2B654DA293C98F6153E68036872A5B756D2C33E7C7648B0968A4B75C0EA79589CB07B0437AEDF524D14BAF52E4E8E86F5EEA7E42585F3B0454043EE82DB3B526DA6C9086CA46442AA138D33B5134B996B001789553E8884B19AA1B002E84A5AA060C9F3067FDA1C4F7BDCC0393B19646FC6FDF78F92E9C9A297E196BD85CABE3173FCA65B31925C0C243FA2C1AB833B969E351C113114E5AEC7982B89F742F9DDFFF15846D8E44E4648BED04F14C6DC450E8D9B88147E78BFD30F800C9340A2D88138AAB98F9A40EFC416D19B4AB5C66E214C23A74331E3FB2D2F2856ABD0D8FFDFAEC9992B63BACFA0748BC804FA53CB9BE97C9D3B9359A159A1EED0E4DBEAB5409E58E29F1DD3F317CBE28A7615C7DA896DC451E665826D72BAA27532D536869DF2F45B6A1B93A7CDBDA65E2F214AF4C1A8C9B25AC39F4E2F4853E892E7A4F0D809064795567CB2E5DBCCB3FB0DCC82525FB3776CDB6132A2EC199AA70D2C558AAE430C3EA1DFF8F09BEE865E5ABF07563C85686B2A0C1A8339620E729CDCDE0A844B547C703BE49E58A0154E00664F661D9C3612B81C429F813E76A8A0486D27CC7EAC0E6946979E9402B2B073F873FA0C7BA888BA197636D87C4C7D4741FD68FAD1CD265EE3E89F32C0DB015701A09068F04BD0505C58EE239217A33414E568A610D2D4AC946BD4AEB5453F958F832284D359AAFF3D6F39C788E78D4A9664A0F4D79F5AFEC0610ADA27E26E348FF3A480F16C1BFB74B3C41F825075C8FD9A15796E0033893A586582CE11A6392FF8581A3E5C6D7EF6E9DB08833A043AC0179AECC2505242C84DAAA4AB5C7B4CFAC3E17EC0FBC234E07824AA7333CE7988DE6CB3EDD47CF06FBD9D4264A57D5E4F0CEE8E0747EDB5D18463E1FDBDA91C1D938FBD135B898D1AA3B7E49A2D6BEA6D0DEA07BD614AB017B023798C560F6335316D580E3F5CD95610A0C0E40256D779B3761E4C2DB2422CEAD6B6D7F068BC077CF2E7EF42C6DE30BBE493903BEAE8D8020FCDA5ECAFFB23D956FEEDA8F90F22A17D68706FFE5FFA975865A596D21792FF7C5622CCC88C2EA0BE56B3DF069731B22C9116DA6A9D75AA8CA50EA84F41E8DBC5757D262C8B3FD0F741CEEFB3CD3FF9E0F1B2834C91ED3D15A5B9DAAE04502130C16A67018A6248B37DE47ED0282E1C7133C4D2E626F27A2827A93CBCE1165DD40EF6A5A26E373599D8DFE2C3F775CA41A279D23CBDE07D697DD52462D2C1878FFF629CFBE70051D6846C78ADF01716BB691DEB014361FA9DC313301BE423F410A9BB92455EA8B20485147D2A3C365F51B1186419FD93D6F533A2474B12B829320C5F150A0A9078D9FACEA7CF291DE2B654DA293C98F6153E680375ACCAAE2BD4315F4C6FCE216D4BD6FA8AE38F0A188A6AB7A85CA96A8C17DBB2D97006C47FF07C9EE493BCDFE9D6819F8269696B470AE1CF022E5FFF6241FB55C0EA79589CB07B0437AEDF524D14BAF5F22E864B47782819500AC78EC26597135BB583190F189109338A27D0055791A0DEA5D8261F9A9C26C7DF1F7C02D3B8DC03D4FA67A81C880EBCD8318B37C52198D048BD45A8752310D42229E002EAF0F5C0EA12CC647B10403890D06BB4B47699E3964AD473FE9A0D5C20EE43F6C5C96C10A160DD7C97BB3701FBE3DA9EEFFCF0A510A7FF543A110CADECF6AECF5226134F2807AB2607799395CB4CDB670A3F1F487AF2CE4CA3F0B8EA4D3CFCD65729436C1F24A4344C7D0C1713C0B5529322880AEC64FFB4E3A8B1BD1EA28448571D7F603D0AC30A62910F8005BCD5BC29389DFF962925A666C3DD3D5A05206C251693A6B34BAFAFAAFE8A0BF96FEF695480E9AA332F6ED7F5D0EFB6016F0B593F0EDA2B066FC8AE05E37AB549335A999A26A6976588E3531355AF21A831E9DC31D12805C28D29C8A19AF52CF3C0666C324AF9F6A1CF5650D72BC9A883E7ECD3CB2DF771FD39AF6231B388F0F85966FB60679641FF35528F85373C71167B13AD8216781C3A081649A1E1D792766F30AABEC2BB335EE6A610585CF074CCD43F7808EB0304BD91D2E08EEF33345845CC663BDEDE97159CCC8FC5BDFDE3CA339EA2BEE2850457595E9BA24D7ED422735137F568BCE1B7E6F16D0F94AFB195AD43F1951920001609DBCAB43F4DB6CBB10CDE443018EE611A2BC475BF8AF96684AAB99D24E03E8209EA0E064526FBE616C8C527390E48C81DC2354C7DDE3CD9673EBE57089706E70D3B1EA3F642D83A4FB1A5DC356801B86DC75C24EE218EB2D3ABDF645DDAA1424777EE01052B997ED1D38F2A55FC269E565E8F2FDB674E3F508795584BC599BA5EB3C2E2ECB93839359980000E4774E93436950CEB9A63D50D9456D2C7ABB517904BAB1AC82DFC3DF59A368F326C206EA092B7B0082446391CBD569B27B2556899FC3E8B23080B9F1B1315B1B95A6E27F970072EE89FF3CA4D257B1AAFED3B610410B441BF7DD4F95FCB5B364673281F5AA47781636D39A82A4D8141F90C206E149C0DA5A64C48C3D3248F289C798B7EAB6FDE3015E7E28CA8C44DC89C2F23380057E3403D1300D4E7E8E38545449D10BF0C51E3349AE060081BE4F8D0FDBD0F1924678D037AC5F8AC2EC2576ECEC0EA79589CB07B0437AEDF524D14BAF580AB402C591CA94B316A5D209A6508D2097DC23581CDFA72EA11715CF62460D2D44017D8F04DB3BF574B1B84D4CD5606F12F8D3D1B510C28F8788951B52BC8252E072C363FDD7501072B469952067E65B6795052B572F5600E60CD4CEBAEF82A3914A2E06BE2687EE90D6EF094CE7145BAF8DD868805957C029495953816A29BF7B90DA9FC027927A6505257C3E56293CB587BC4BD594EA26668C06FEB66267633CE7988DE6CB3EDD47CF06FBD9D426479495D471A32AD1AFADC22D5BACD44477591D872D394BE10DC917FF63FF3CC3F5B41EA00EDFF64C150C7531F5634F1360CBCD6BC1611E2CE07C987FED0DE1D454E871BD31E6AF9849779CBB330D871CE21448D2A59F2ACE7EA9548CA988B301D3343B2107D777E332B8ED8BD043D8808010686D809368529AD43586963474551A8999261698C57513E637B5E6EFDABCE21FC7257C6079DF692170E0065674323F710E763EE3A89423B6E0204514440C1434C196A670C732FF338328FF27E712305C28D29C8A19AF52CF3C0666C324AF9EB2E3F88B7413C33F736278C74D89B3C4CFCD8FCEE0DD7AAAE06C3F0AFB7775BE190FA4FBCBB19FD1484602AFEBA5972C38E8B132588FCD6BFB8CB7B8E67F8CD6E9747CB7AD4FF463C6CAB9C3D9AD1A467E88BDFBAE0B4F29F6BBC1861986E0C69181B1086D21429466DE1593B293FAB41EA8E892D050A3878B679562A2FF4C4B48F7AB792C504BA921893AA271F7780657D9141C04C46DB34A34BFA4C47F1F53EBAF8746BC1FCCFFB43F0616ADD0383DC3A6E8B770DFD7CBBA538BCD210914CEB2E799163E163C6A7D79FBAD027291C14C0D5C2ED3D5699C1EA5344DD3A56E64508927480B25B4D36D1ADE3E08B0E5E41FF35528F85373C71167B13AD8216782DE60F6E81CD5E10D3D279E87B8EF46A36B6DC901FF6AAA05763A10334ADF038DDB6C968FC3CEC9BC9CBB9A6F3B2F097906E179EB4FDFD328EDA28B47FCF14E4CA3C8BF264AD455A817857CC7136A0E4518270B935D52B6AB3EE5CE7593CFA4AE1F9E274B9C918F2A9FBD323E83F7A8B0C9340A2D88138AAB98F9A40EFC416D1F37977067C59B4ADD60C2D4343A6DF95DDA0E83B40CED0D291D073D53DDE5B5BB48BFCF8D3A53ABB3FBB27B19D711A547DB695A2B3576C9129C9A29219E8535B5DDF3A71F1B30AB7C933219AC3E9F9263B083A12CD055F55F9B54FDBFF3272AC1B36CC7B3C67DA8A559E42E59D9F92A443AA39F890F6704590130442378F82919DDE5DE7C7AAB44DE9B4E3F5A57B31CBC19C95BC788EA483D88A87B7A0365A49AFEAF09B249945E02557FED97996FBBDAC3FBB12E58FDC2B770756BD0D34466904F612918E104478A44FA5830D4D8D4E8014F570B78B86506571095A78ECE65E60DEADAA9954354B17693D82E87CD6D232A71165A471703EB3DD25285BCC83FE651684DD5ECCDBEA7B530ED7763A68D9008BA197AF7F2061F88E4B30AE4313D735102ABA1C46D78202A0FDB667E0030E75EB6491F5EB653ED8758F003A915C896CA393E0E89C2BD1C4A16615C13F399B90B0EF15B26D742D5A8D9D3C2E5C77A1C5473858B50B0AF63F51DDB1A0C332DFACB228275DEFD66C1DACACCE720ABB62BA538C7FF8C32892939ABF9C659EAEEDE9F6A7053444F4966AE58910458DAF509D2527E3CCF57906FC8AF79561DCCE0721FC7257C6079DF692170E0065674323151C0D90564EBB08D471152227280A72BEE1237DCB03FB5A1DE7C1005789F56593D23AF9467EB995630A2590DF26B7F6B4620A03DFB1328E73FFACFC1DC96592C0EA79589CB07B0437AEDF524D14BAF5F3CFBD702B465312D1385A50893132EC5F609D7A6E3406D1460606A6FAA8E62A38E46BAB9F0645F70447212E94AD982B8512C0682EE2EB6C8AF927CBF3E4FAFB5C582D1D0AC354928FAFF8CFC4A8557474DC19A842D1CAC1A70E5211488813C44A69F14277C3780FD8CBA3636B8DB30B89256CC5F519746BC7D78F7A3712D413D5C9B1C49C1BF7D657A4727AA51C3FA2DCBA2A665EE752EA78C9780925A06A0DD5C9B1C49C1BF7D657A4727AA51C3FA2D6A8225E2D5F3BB74DBBD7EBCAC7D2017E90D85B3C77C0FCC49FE301727799C503D4FA67A81C880EBCD8318B37C521989E084A2A7AA1ED67B4D5B002028E786807A54FD7F2034514A0C3E601335FC3BE39F1F093355C1EBF82539386158134659753E1704E464B4C4DCC79646664FE8E7E0F7FB6D72FFB97550E301A5B2B83928151EA935C11E8CA3A19BDD6BDD8F5C547548D7EDFDDDD7A0985C0083B46010005C28D29C8A19AF52CF3C0666C324AF9AEBE964003215D9B42BBA0235C008E83AAB3017060DA4D3869E70B6F13A4921C52E734C5E0532CC5CC9E4F37F2439E94C13A9942AB30E124CB2406182332A7944BF181CE62614AD5C88B64693131FA91AC587D400978887B1B94DF79F580DAEE39BCB505DF889E8FCDD5156A0BD29FC605C28D29C8A19AF52CF3C0666C324AF9801A6A9362FBF4B57F8929CB0965044A5E812B96D9B5B313ED44171F241A61C04E909771F2A1F84176DDEE101718233A95C0B73D71A39452816FCCD452BC6C4CE601A2CB72C1B7CCF748EC4D882E64A817D729A8A9C8E792CA61A83DABE3CA321E38D1611DB9E0035EDB1C7E7BA812E9E326388BEB807A41ED24A1E06EE33A593B643FD5B2B881BFC21AED48BEB3A8BA15053C7EB28CC4011D4CF66CD8A81B5039EA667BCDF93E8079741F5BF4EDFCCDFF6AB481CB5CBA2601A9A1F172D022D1AF8CD20DC7090EA4852F04E4C282828731E93D4068B8D85621C75C35C27081EA1EE50ED98BB7EFD8E9B7E2072F7E1E4581C33530F536AE0482D898FB005200ED602AE6E6460103BB2FD2999A5738D209FAF98C72961D5F873F8A4634BB1F3BAD24104435C96AACE15780099B6642F3D511CA9064D021FF37C4F90EF5CF75762DEA546B7762117FBAB99E2A92ABE34711FFFC9EE1183059EBEA0A45FCD91681CEE77006425DB8F2F2F499C6840C8D431E4F417E03F6602689BCC51B685C4C8E5BD3BB00D2379EED5B016E970203105654B5A5D8A7A199200C96C845E979332EB05894B4AB36C89E3BF0FED36F97A7A55B44C3E11E54CF6BB7F95C4020076E991B9478175E22A6EE6B67AF3E8291E303DE2C5C93FBC9FA0566623557A2B41FAFBA18AF9A5FB463C9E9C9A70BD7FB0BD16E5B103A734B7BF28BEB0A14A589BD3192C175E5B509EDC382FEF3A6A99302D0DAE3FA1DD5B49E837DCB1826EC9921A19B16CC76876C08296B4EB21E2DDBF49BC0B2A20A027C3C69994ABD2361200FFA8CCFB6A8C6643EEFB73FA2A24F4319FE9205EB689B285F77A25B7946572A4E9C9F09CB871AC2FB4527E3B7B8158C5AA8B997D6CD152BF45A3315C3C2A524865BBCE0542A5CE1DD6A71B1D08F448E5BF4CB920B64CA874FDF1FED718ABF65FFB008436053D1E9B0AD97001EBAE0B87E86AEF14DD5F9AC13F20B0CB2C4F50F7EC22116DE98C45BCE676AF3D6D026B03B39681CB92E94ABD921F99E71BD2BEC222154052A3BD454B5C92C39285F915649A3EA817735AB9ECDA654C49DF5EEA9084B30BE9F3D2D2513D0209C0498BC89D4AD116312D4B446DB811E0239C2ABC783B8FA00FB26A635FF754B76B1C2679862851743E2E5BF86CD44061D5958E05467AD6E4DA3BABC8754A5FAFD26BB892F3CAD2D5540F908C8DBE46737EAFAFE49D195F60CEFFCABEBF4380285B21CC44241D38CA1F3C5BEF4CF3FA66DF25C5EF5CC67737E14366134D0DD9631DF2C5B245E1017EDD0DC8646A873ED364E2404A40EE35DBD1A1FB03093DF6C1D47442F0C5F47518869EEEBD1555A52660E18D06BC7A66EE62A83735EB75A503E0A612504FCCA9A5DEFFFE51F0764EFDB4636D7FCD9B7A3F7408C8F5C974DED30DC7B447D1EC863A218F1FCD54F6DE7339705260205F979650AC27241C4D98DBE075497A204AF9EA62CDC5562E768BDCBA0665F77B1FC3E5F7D9680A5979110B65453E0E5D773B0E6E5200A6636F2E59778403DCBAB7BC43A0F3CDBFE6A21ED6EB5DC617C55FD4819A2EB7C5D7E99D4613F918535DE881E38C7DCA21FD3E84AD5734EC91D72FCB9E9001641089E6274FAAE7806E68E3A86A1C8A5F29540ECA3521A9D3D11AE42B3EF3A67E951A85893F578B8203F555DC683BAC144574E5A9B0B09F7ED0282E1C7133C4D2E626F27A2827A9327BB42185E5330D4D6A22FA30B17313B2B636BD505BA703F3A43F1225D49ED941FF35528F85373C71167B13AD821678AFA0B5A629A0C6F7EE91A057375360ABC0EA79589CB07B0437AEDF524D14BAF53CC11A9D3763AB0ACD845EE72CA3E7418E252CE748F4D11DB71F3283707522C113D2B9B030BCE6E5060EEC5BECE25EFB1E217DE1D2FBA5C925A36C11A45A39264D828C04AB8D65F478CD4DDD9A1B99905456DF0FB6842B1E33FDACF1162402076D62551DE6477CFDEFA748F54F49B6C58A0A8B7A925B9F6D2EDCA5F70CCA9446694F4F2A70CE82075B89078AE10E3083622D9EC658712AB9F8F98EE0919783C121FC7257C6079DF692170E0065674323130AFEA5E8DC8C4B3119B319A83E817B85F756DBBF3E3FDB925C2628F2294D38FBA107752E8609C83B3BB3A67E77A769B56F17EA3D468E0BC78A7D47B82C676C05C28D29C8A19AF52CF3C0666C324AF99C5BCB71071114010CE5500B358BF4CFC0EA79589CB07B0437AEDF524D14BAF5D602520B5C3CEFEBED377C19F7C2AF3B13CDB7A1959747F253545FC81C19CC327FBADC0C930ACE112A5173B116D438CE66248B7DDB757E7A1792787F77357CE3046EB305F533ECD50C813AE29E2608A748C81DC2354C7DDE3CD9673EBE570897493CF9E38A4E3DE62AB18B1A692FC19A24067C1CDE5F420437CEE20C18CF40E18CEB5957C2F46F11AE115A92C708BCAD15DBCB43D375A62B25532434C9CB797207455BA4517EB8A4254F2B2A0C54F8CEC8BFEE2036E9B1CBA72037B8AB699BB72BD4D322123D437B2A4C5341A9ED7B89EC91D72FCB9E9001641089E6274FAAE7206E61EA76C697795B53E14D1830F0EADD8F4A924BDEBE254DD7288F66C43BE7BC76F1471096AD3AA6980CBD2B0154E146C990CA0B52C562AD7CA21AD936BD5A32348CFB29058CBFEA91C9BAAA09B54334A9D2206858A323EE752BA209BF075E1BE9E92DD43DA126704227AD6C8ACEC9C07D0167CC59994D73253E78BC50327EE2383A0D49B7CE1810102876625151FCFF0C4B8263FC912299D0593B924639F4ADF3F280A832B20B79BE51F51781010C833E21F464BF3C84CD5B8AA17B0DB6846F92E92013193A7192776D562A15740FF046B622351C2FD5FB1ED9C3A84AB4F49C9DF4A3E47947E36464863DBCE729586EBBA0DAE7282DE6459936D55336BD0110E5EBAB11167188A455736035747A94792F41582B1A13DBF325CE1451C30DF141FF35528F85373C71167B13AD821678773B0B220363D11B26EC7FF0CA206252BDCF073ADF9C1F7C69BF5E2CF9D088E147AC62094699DDB977F08722CC1D1A471064B1FDF47E1B6B15F1289ABA62F62057D87A0998745AFF3D9AD7C6A05605D3DE39E5FAE2BB95A3C84943A78945B855168E68CFC94B64A7EB1B698B3CFFF5DEA189FAACB6CCDA183D4DE30F4094CEF3582126877B4DE65BFAC092CC12B2BAEDB2C31D10703E570AFBE62578528A27859C7DE619BDF17733F7A80FD26D9861621EB27FA30B79A7F66B146F3090B4F42E8E65C181182E4C57E7DE6A6979158016C933A7A8BC571FDB93463510B0295DC9D633FCDCC6639DD8C1B60837CFFCB39916D0D7F23CB8FC26E2DC26FDC34572154C932B56BE7C884321BE1D37852064E1DC863053C0D1247C3AB4633D7D51A1DE50CB505AC71D99C1D57B2437FCE495BA0A078CE9F9CAFE2E946A2BAB340A1C5B1591C199D28D761CD11803413555796599BAC31C61E20732898D50C2A1F4A818B79DA78175FB9DADE105FFB7AB95A2059DDC4ABAD841EC39B5C80AD70F43515BD9756F809DB3CFEF7E0F85F0D50D2B54DC9A1149C68DB091A5F5B6B8F4F8CDDBC2EE58A460D826E8032AB03360C03C21F10D3BAACC2F83C4DA443D6D6FEDCF2D95391FCF84C681E5342E974FA0824112B122182B86062A7239E2CA146FD1D0887EC0236A96EAFA216962E780AA905967E1F72A485661B990DA62CD535E64E6B17176DEF76C248B1DDF33A991D7927E62348CDE86AD987CA06D9D87110CDCCB3108D374DCD493C4D25B060E21B6353B561A6C970543D9DDBF94C3225E91C11AE157E502C3DF2D4E693B54D0F99C8F11EEEDE8B6DC427EEF408C0B35C8D6A48B1366F1D54BC29AFDA8296AD7B828C3813496CB0A7C094F05FC1EC5B0D4789D4917CBB0518571533B17C89D4D501B7DB15ADEC2099E66CCC7290B7676DBC08435F622C1518289042663C95E83099DFB0AEBD2A094759CFA6B924E9645F407AF56D95F0168522F92379D4A235D9274B128D5D20BEA2E33AA199A26BE33692438F35AE3E4887596A7B21A4F46286E5F94F4A829450014225B9D5B18536A8042D3EB9FDEC68EC2177001A10DCDC94D1D047F4138E9ECE19F179BC105FE39A4DBE86B4564878A04083C82C5B91181540A0AE1DCFB1B92289D8AC15FBB504360E6136FD7924242964139BB14D59D25A0B999930E0D30990D98376ECF101E3510E2DD605A64A7301804DDB1454D479D208A4D5929F311FDA8D7E8F0A38FCE7AC22AA98524138EEBFD64049F667EC1404388EFD6F760862C71EB223A18634BBB0D3147254041C640F1037FC5EE323B8F9C6BA18C16D7A1267C6D9DF871F377DF4A8783D3FB3519A06E0467A9FEBF999122E7693B82015B9A915EAC60C4A4F5D8112EF27C3AC9DF4AF759AD04E0ACFC3F9D793634F295391FCF84C681E5342E974FA0824112F709FAE6142DA20DD0AF802C36A45FF0CFEE0D0C299526927E2569D98EA2FC6D5F0168522F92379D4A235D9274B128D5D20BEA2E33AA199A26BE33692438F35AE3E4887596A7B21A4F46286E5F94F4A8E01FB5F41E32ACFA14B1AF7263FC1E172BE960574941FE14256E0748B0C6EB49D21AD9286E1A610C27677305D31B34252016F50620496A77111828928368584361FF012011CC89EEEF5A47D58144A524665A9DFECB48F654E8B8CB66C0F9323B8B396BC7B0C10ED0FCFEC94883A6F0072F2E6ACD78A2BDAAAD627DFCE7CC78AF457DC2CD01884CEA34DAF8F95D67665AF1D899A3E0B2616ADDCEEF8D29307CD057A6DF8E43779824CBAB01AD16FD96F5B1EF471D2FB5C53388F5951A07E0C18A3251394491DEE06996C196DF89A50B459B9C7587381A2CBFA766156A174736DBF2BA82DBDF197C6AF6BEC5D28ECE2EBDA283E5429EBD694D5CB787BD47D42F6AD3145F0D50F7617D77AFB8035AE4953E35CC60AFA48D9F06088912135461AE8CD43012DD69F11637827590E2125B808AE5E458F1475C71406F28D5428A648824B9547B082C0BCFDF2D157289B32078D39CCBACEB8F28D3430FC5C9ACA1926AD60737595D7AA2F30B59C790F2C3114BCF7E2E6DEAECA3C502FBF573DFC856F3DE8423F21CAC9285172F85A6F44FD75529A8DF30E57BF156B9C4B7AC614438A312886E8AF5A63B297F390D5B217903B24DCF15FCA0E9BEE5766791688315522AB6F11C7B947B8F6F8670C05D2635C31C9635C7891C322ED398C0FFE0D2344E06280AF0A0FE97DC1A63021722B5D4D5A6365F0D0733E3CF94E5784561C9708FA804F588322031662A1D993FBD2B7CB0F2CF7FF6BA1C4D0C86EF58D66912C617139AA44ADA01E266EDB2C8B9D0A25643A5F526413FAB629DF09AAFC836A2FD56227428F2E7085188F8962CF391E4CD265523D6E89D4F131DC43A5212CBF58B0A80BF65D84FE5D9759862C753E63356EAEDB2676A8470F61040C40B5E6BBCA6F01FBE0851A892C409ADFAD3097B6F7F631F84B1A006400F30AE24D888468A9867BCD3E4C07D51BEDB6A52F5B86F054F60DF061BC63C43BA6176E4A5B02E6E669D46189404B709C2D37D4D92213149E02A3B285B29E41D5CE24ACA35CBA3E93831A6E75104374369AFF531C4B5B7405E711EFFFCEADCE1F1CCA5C7AD3E4CC89D2581CE12907EB337AD8CE4E54CB222C89C20F539F1161485793B5807B441045BA843C007FBD664A153E764C7DC242448719B2BB202D98A180302D1B083DC08E12C94C7AF80A13D0ACC2F98260408651DF7239F286D5C5ACDA1A5EBF78F016A5A7221F226561971E33A5F20556D04E41354024427146B00281B54223491855304A4AC1173999CB9E8818BCB8EE4E2D9DEAA51E495EF44AAC1637A6B45D199B5C9A45EAB8B83C4B374BD432BEAA545ECD974971F12304DBBC1C8823164996F030AF245BAD586C958657ECEA362BBA51C384D99E3B43F24AD84697F965D0E5EFB22AAF36241C7773724DAC4CDB77F4E6C87D2386D6DFFC552DA47A0FB32F5342BC4A0294AA9066E291451F6D7A6CC428BDABE898428A29223AD003EEB642978AAB9D8DE9808970B442121831D04356C3161E8251B13BD6F6D0ED50E2440C7A59B3FAE513B6FA16D7345E17FAAF1A381D0ED1A7754BDED1F58EDE6989E7F9DA13B8CA136C50BD36638B3C3BBAA81F883885F5449E3D595B9CB309D5D607C37A91D26B09884104443917ABE1C8255DD34A77FAA3B746C038EAB5FD3C5499836A35D7D1550666E02CC4D9317680854094E107C71D961E2586F64C1599B2026C0C67C9DDF38B6CF5D4E6FA8A381F652743316BAE79062E2380DC916B7F0496A4F67A9655E7A7290D3296E619B14B370291B7A2AB2B3295260205F979650AC27241C4D98DBE075497A204AF9EA62CDC5562E768BDCBA06FA1803CC024FF9295EB3A7DA79B4F0ED83466F8CECCBB40621708BA729FE75376A7B53C2B1E001E3BE5047DC553B7405DA146FB10ACFC73697C9C4C7018A19583B1557093DD466B8AAF1F8B5058165779EAEA59BE175C862B83B87264990C039A3B77D8B19E3A6CC22C70087E90C1ADB3B51B1664870371DC8207A3E155B1836E626F6BD4395121CEE9D11BD9160BF221F80BA0C6F0DA424022893A1B583C7088C0B261CA36E37B40B84540B4DFC25E55D8C2E8C6E03B5D487CF09662503394EB700FAA44529B9C30E9419A2E26BD6B2E676A36A9A8EA37E580F95CCD4A38B4E651CE9690794F463913732718B569A8501B35FC0E90CDCCE1724507AD13D5ED7F07CC41D1BEFD1598FDDCC83F37980544E360A3FF34F0B08CA1184B3FF5219A04C43E9B68782F9594758F49A6F3D342B0D812C1B13A620343F15D9ACE0022E33BA499744DA27F277F914D56DE45698A741FF35528F85373C71167B13AD82167834B08BF720F2414C19F67E427EBD2D4D14CC2ACB24F7F5F8FE32B35982FC5E43030188027E824EA2910708DECAA47ECFAED42413FEA5137E8257CC0D4E949B116C89784C4BC37F5B02614941CED6639676541AF4DDF436980BB7693C813E6A9C44D6FBDC48E2B9A40AF1EE67463180D4705709E78F7FE799EF00ADAD414F83FA3BCF391E82F3C26B90520C4DA669ABF7DFBFEA315006F450397CFAE72EB9BD2B41FF35528F85373C71167B13AD821678F3E62A2C6306C92EFF436518FEB2B887130AFEA5E8DC8C4B3119B319A83E817BC1AB833B969E351C113114E5AEC7982B45FA2222959403E2B2FD6BDD4A56D2A4E9568BC1830E91577F2683A424773DA230505E197890167509F51FEAC10D63A3DE33CE61E2834CCDE976EA39B9C9CEF30751FDD33271D05743FEFC045A975D0205C28D29C8A19AF52CF3C0666C324AF9606C3600C5BA9C05735C636212AE00EE05C28D29C8A19AF52CF3C0666C324AF976C444D691CC6363DF8F5E1ACC4DEB90C3C84BB5C3DA8054A0CDC1CAA68614ACDE33CE61E2834CCDE976EA39B9C9CEF3F6D0C7D315C24F7007700992215EE31C0E5FD4E6C8B7DC718A3F26D468931CB9EDA4202C51A8100878F0259D6E78D6370C9340A2D88138AAB98F9A40EFC416D165A9099F3D8C2E642328B84175E18524DB2F5136BDFC63A5C442B4EB71D67074DA31D80A6AEB5A00155C73FAB3B374888A08063F24539FCD1579DAAC2A6DF8BA36B6DC901FF6AAA05763A10334ADF038EFD40ECBE72A1BFB9CE8AA8774DD4B1F21E2F1B6CB1966010B97E2265B473A29B38D3406B97830B6FCD9410DC3FBF7BE63937B0129B949454EE9EBEC761CF05ECE5C9A603709C2BBC9561D22AAB0827C5C800BF685ACAB3A15FF9EF4627B5A045FFE3C7A552B8FE7458E4D4A55F66F531686B69A0E65F120FFBAF1D63A65619DCBEAC05C344A9770422194F87CB362906887515FB87A9CA56CD78E1D860C8E5C49DC50567382E2AFDF9D9F2698FEAD057725DF33429580C2960646228417535575DE843733BFDBB31CD65842DD19DC82F1835E2BA29F02049756FB11606EE7BA393D385150A4E2A381CA50EF60E503DE0E7D3CD8AC1118872321C99BCBEDC9C1317C96F91A8437983D36E782336B61FC36AC68825B1D1DE26C17E4B98F8549E206AA207DFCF13B366F018F1975ACED82EFC606F9904B45FBE22C4483A243C2F3CC533ED020D9F2D5D8DE507E9AC031BEF72A03C4D5FADB162B4BC0D0348CB30CA16AAC4A7E287D7C407373AC0FD88B66C6E0FDE0B9BE374900FDCB68DC218F755659A7038813EED7479A1FE0337BF067EDDED5D58FC3F762650B152499C57499447F4B494815F722116584213F98D4846D7E934B259916E66453C3CE956B7D9DCA92879312BEEEB5BDA5A45E9F7444250EBD8982591D5CD660E22D5F46972CC19DF2799F369EF0535CA58CA18F79BAF5C60EDC77819352C12053B113AE113D95750E232C756DD91DB44FDD225C2F1DEAE14DB82FA214F3094E2B91B1AE2EF8B5F71DE619AF867CA6223135F2B596C406D22C4C626DC15300BE20052DE1E49E61204862D0814D2A7F145C778039BF3CCD6F6C5F739F073A0313C72284411D65A28A08063F24539FCD1579DAAC2A6DF8BA36B6DC901FF6AAA05763A10334ADF0385D020126A63F933CF3B92F5C797A127821FC7257C6079DF692170E0065674323A086F526DD55CBE899B1DEC4E53DC71B11A08C2726D1B3575B2278203F56348316F4CCC3EC7CF487AE61DB84F935E878B05313C3F0613C5BEE7E2E566567353A5F25648F5E15CE28B3A1B9C6E3E2996295391FCF84C681E5342E974FA0824112C4D500B99DC2C206A62CB88EB33395B774EAC744B0C62097D8D50F43FCFCFC41DE33CE61E2834CCDE976EA39B9C9CEF3EC58EB2C60384394FBD3FD23B138E8A0BA526F6F4C1964F83C03951BC8FEBB788660015823BB51255EC74DC1974A29126E9747CB7AD4FF463C6CAB9C3D9AD1A4AC74610134768DCE49DD211F29129D57B0104B4F52ECA43EC8A4E54F09894973CF7A0F958EB82E785FD669E0D0723F1A954DF1605DF2EA6EB30A9E3C7E5853AF169AA32069728E4095D817E6BA020DA2321047D5516EECB6DE17E17F47819B3D5E1B9D5B07889AD00A8CAD9F86CD5753A6D49D45FBAE46B936E892A12B162A1278D0E675578B8FCCD3762E1CC97649EE81E07CCB0E02F5743CD9454618F6244628BEB08C56DC781560F27E90641217BFF41975CDD8F88180FB6749B364D47B7BD9064B4F85F2773BBA45DC865A9D32CFA2A470527A6497EADBD968068D02FE57336FB7E8CB29DB344343255DD767E4BB846CEFBED4266EFBCED105319701EF66D1AB82ADBA18220DEF216EB52D909D7C8213BFCFE93D437F89B5CF0D4E621AD15F25648F5E15CE28B3A1B9C6E3E2996240ED516BA9AEEF92ADB29F3A7A69B70D05FD3D7D38193717FA603738A8BCA29E874BADE9CE6DB4E54DC7CBDBA5E1B390DE1AEDC5C49478E0D029291F3A98D3154F25CBF61558AF773958E31D38F11B321B7301CF4A26B6C5D30EFDE6C5FE5D89C0EA79589CB07B0437AEDF524D14BAF556005612042EFEE55F230EE97B65725F2271413966089C1BBA0304E7D6A475C3DF9A626AB43D0CEABE5945B40BAFBEC9AB26A8367BCA6FE12782EAB8DF36D3859061B9C14F3690A5186B07C0AE5D73C9080B431BEEA1D327767A180F2AA72F2A6104B2311E7A841115EB885BD0723319CA8A9A487744D6945EF812978B3A7E73A325B22744F920EA44DB0256F6DEB659A08A4CF56135622370C8A1E9381601956A4C2383D8242B3437E4765C62594E2FBF52571A07CEC204879590B7BAB7FDE405C28D29C8A19AF52CF3C0666C324AF9FD3CE85280A2D758C01B7D8CE889B8C2C5082D3F0D2E4FB1255E093D2FC7B81F692AB419C5AA1D32A030CDB7DDFCB256DA4F3A5E3D890E785195DB37FC0516B4111C47EFA76539A16E198877A26C5D3DFA000787AA7191C3311B4F1E7328B32E0D5D1406B4647450A8D69D26431D184DC3931792B68CB5F619AF5E45AB94CF3EB9B628AAE240F71D8F81942615A62618DBDCF3290826EE9B97FC3AC3B23BA5FC7961F38BED9E636873621A9FFB90A50784AD1CEE38CFFCB9AAD3E6F7BD78DC75143A5CA235CAD1106F80B91D43A669C5DC95704ED70EE462BBFD35957AFC94DEA876A3096C23A2E08DB4619B5C48DB7F3FEAC8DEBD60642424511DC26DCE6B744EAA34F4D0FFEDCB4C8A1AD244FEEF54C1AB833B969E351C113114E5AEC7982BC2AC15EDF8771A6077FCDAE3526187AF2CA7927920D77B85197B8E1D302B7BBE3E0531BD69AB22A4A19D51F7C795668FDCFFF5B5865360B6423275EEA9CD092462F87F8E1103E18228E314AAA7C3290BAE6A688DE97740003190CAF86A630BE75751EF136C99509A91A6BDAC5BD970B598876D4BB387E241CF866159815B4578F1575685BCB7722E3B87E7B934B75344599AF72259507AA1B3CCF43DD82248BBA22082958DE6E9FBF7B1A3F9D4A4058DC1AB833B969E351C113114E5AEC7982B8671DAF4A2D18DD92C974D2356C611D605C28D29C8A19AF52CF3C0666C324AF9A3D4630228F96E7B25D0ACAFF6A6ECFDB75F97F8C7A81155C2956FC44E079E545DF647E3985E9C1151D134F0E6350073E06B5A60EDFE80A70E8B1222310C7CFC1A639AE85B45F3836BB04BAB585541EB2534BE065AC456A902904463FF609EFDE674436BE5D8BA29198F3E2E9C905569D131EB3A99CBF5B66270D1FDB90B1642653E21E9863AD5BB6D94BFA52C86696A3DC10C1F9E880E5A2BF4840DD77A5BB0D4C5472495C369FE7E96358A2FD4AEE2B079A652121D68B59E09078BC05D425F704B0BFA9579F877FB82CDF89505C18E111A3E63D3FDF2060D6D6583FF6F251CA7C65AE869512237F68A70FE61FCFDF762A5478716F27529D07481C9F55C9A09C7BA845CC367D7959D4BD76341D4132C91C827DBE187AB866B6AA49C6C2882F20F328A1C2B5B06BE47B9A310CBFDDEEC5075C8FD9A15796E0033893A586582CE345C01AFBA363CA5E13C9FF0A357E0F5FC7D14E0F11CADEC794EBF788210252643A665395B5E11ED9E6096A49E6C943776BBB2B4F211FC11560C311EC44D4C2EC454266A1F9077EF38EEFA2C3F00B34B25914A671D127426AB198B310C858CCCFA621259B75DA53577AE2E9A6752348EC0EA79589CB07B0437AEDF524D14BAF55EFBEBFE72B69CE04E1C72A52D3F621CBBAE44321C30D3320A3FD5672E3B2E062BEC43AC9FE9810C1BA1790C0F0FFBECC0EA79589CB07B0437AEDF524D14BAF5F1575685BCB7722E3B87E7B934B75344E318B6BB4703C76D2723767BBAB22098AE2BE03B82A583CB6A66A8442663AEFB05C28D29C8A19AF52CF3C0666C324AF992EADA4C79EFE9BEF1273F0458E398A5E85FD04E7C7A67588A9345E8B43098FA835CECB4804B953B65800B2D34B0954D152D19F241CC50800094FABC437A7250FD2253D3129C1B32D8B45EBC7F1FADCB5F25648F5E15CE28B3A1B9C6E3E2996220200FE661CD3ABBA9891AFC80F217CDD640082B8077A1E4AEF8D023F91B5BC63F31D4D52077EF3EA6AE62786396548866B350772F6CB61A98188F869F21A144A7CF291DE2B654DA293C98F6153E6803EDA4202C51A8100878F0259D6E78D637545421AF73DF114174D1B0CDAA710C0D4671D9936E9CD93307F8F879CB2CF3C50A1A7BC177FD4D38ADF97ACB09576F2BD91EF1D4A4244F665BD0969D372749A305C28D29C8A19AF52CF3C0666C324AF9A754E6E19DDBB9F189686F1F35C34F0EA7CF291DE2B654DA293C98F6153E680311F71EC57235C517F3522784A6C0F8E1BCE10A712970838484F7BDF1C21ED3DE7CF40C8501C0585F274999EB132F9148C0EA79589CB07B0437AEDF524D14BAF5BACA99811B5E905C8C61EE4A94E212A40C19BA269A4B8F14765A30030B7892C18203F555DC683BAC144574E5A9B0B09F7ED0282E1C7133C4D2E626F27A2827A9285F8935E3588D61BA19C7C429F66A771CEC73C324FC53CC73542B5EF06719779D321F8B0DED862E02AA603521C2AC4947AEA081E2B1F68D73DBADF72DE65C97C1AB833B969E351C113114E5AEC7982BE9B96C30B931E8648050DDE9E16A53B48596249E2869DA7C56246EE74C5719C5BEEC6067020C3EC17CDC8E8953B66F6EC1AB833B969E351C113114E5AEC7982B27EA0E176BF6D98E156E907826154E5B790AB955204CEF0A527C6C705CCC7CF80C9340A2D88138AAB98F9A40EFC416D1CDDFEF3D4F3F0C82F6D09267FBD21C7B929D02085F5EC0D83A0E651C3863CCB3035D8CC452B1884E60C9C58AB79AE0537E103689FBF7184F547BECD5AD25C635FA921FAC0ACC9903B448812BBDF67DCE05C28D29C8A19AF52CF3C0666C324AF9B9EE558BCD2C3970430837EC85D734B87F95E78BF6A283BA9988B521A47A41BDD9C0EC00939DEE2574F7875B3B098A408873C10ECE16421EB807A62B13FCAE375BB74D628AECA3BD9C19C2A8D50946E8ECE0CA25A2FC51283E43C0DE5A9875BDC04E908E0C7902E6AAE0A5B0D65E5FDF1C08146E6E6AEDB3BAA00D3AC5B9DE05232FFB1AFED78C4276558BB008B6C6D9AFBFC143E524263DF4D1BB5D5777F3AF41FF35528F85373C71167B13AD821678F83137E352B0FFEF259E50E333C633E78E7385148F1AAC58BBE4F90A0C948003C3F5E82C58C968A4210D09F2CC641BD2AA332F6ED7F5D0EFB6016F0B593F0EDA42F3BC800C4A5BE02F7D79C637195077C0AC19B39F674ABFC6045E6BA6FF3ACEB3DE1BC658F2F3FD502A8FA21FB1D9425FE1AD724AEE24B5B109BEE072659D0F04DEC773F47D102E132259B565131930F80C3EE1ECB1F16D087A491490472FB5E585E1DDE753D745B4A310655470E695E816E7AB922962924F2CDB0755AEB923A4AFAA64E8BA1176C1A96C3DFE3AFAEC2E3DE96005A0EFF6A7550C4A9B19E509DD295598454DF0B0EE35C1597F8E58015142824F1862C2AAF25D8D62C94DD48231029748140F00642435198C33FDD941129186904549B4CDBBDDDED5A93AEDEA3C2BBD0E9F231ABC8F3B038ACA0BA20F839458E3498653DA238E25A10DC152360095D9A524CE121ED9C0CAC42E76B0390B22E243567E4B7CDDF1E1FBDA6036361F7DB11E6ABD76113536595937372DA9ED714F146CF900DA05140D3094A383EC13021C8409480180F61F473429A59AD961CB10FE4C1C71311C8AF77448BD550F4BA4505ACD43CE1A46D1831B22B78940F652A8D0C5DD7B9F55D0ADB8F9F77770487B016CBA338DFC8FD79B792F67F43E7B67343A19CED970E3BDB606BA72FCE627E8E47911A1BE129811EA9A958EF6952FA7D78A12DCB98FD7978991837D72A16122CE0182D22002982AE940C2022A35356C731CC5D511B6F199BC1E49F783D64879846E5301180138DF9B54285F8BF636D1F431813E6E5D3E0E7C3B63A922FE1838B26A744E21A049512F991A00A41D2ECCE85FAF34D5FD2194A54D12563A4FE31420B9C4228FA379EC22B7AF8214686A2F3B16E93BD32ADDE9DE899FFEBC494C6381F6ADF39A8C2C4F2EA000F9276D5F32D2F263BCD7C1E547C9F386DDDC6407DAA7C52F14A18C57B1F87CF0FDCA5FFBFD6E9D07BE8E82C4D75D9519824200FEC8667ABB0B63AC4D10060FE925B6000364DF0E30FB4F1FC4237FE8679807954921EB72F1BC84B5BDB65F6BF9BB7D74BA3AE6319FB682F26C3A91791DB1B1CF9F33517D61C766E41FF30DD64385DD5379BEDFA7BF0A04328513472DDF52003518676D425B9F932692150E43D5778DE2D6A54D2256C5ADF872B516C41354EFB82DBDC1812C561A499BF951FDF94A5C87B137947231B9A9543E5356CDF43BA11D78F59FEF29F4B474D859BFBF16C0ACE0D0E51F9132BBB98D0C69EE385D6E45792501B80BC6C0B01626DFF645304DA433A37D311BC70BF53E0AF1AEF81963E6A3CE7B2E4450B87B01C84B0BDD220597EE8B17DD072CD2E4FCB995CD4E6E5AE54FF80E939E6E40241DC7B93E2C118C3DDBC9045634743B298AA00862A4EB4188429659382845A813E9D4B9BFDA2D4B16D24DF0E39AF7F399F27B25F3B8612228F8B12050C844D5F2720F28CED22FA9E5161C02EF2F373CB45A1383B09E05B11DB86CF1C3B662D9D6C023EA07FE6F2C2C6946C23EC9A45A066AD3D184B8D5D500D846EDD46C8C61710B5817C576EDAC0453DA8BFDB759955DEB87E6A5F75D95AB0B43EF8F0848242966234CF315C1951E91B2C55D1EDBE3EC1419AEFE2347C59D649E14035D9899B29F14AA6085C5CFDA25BAE52F86F4D1BD4556DEA43CCDC0A944AC903F2F89A3FE4D229AE349B5509B140FEF64826092BB018CE69EB7685AF2A6A57665488FC4A5B6B5A0D61A7948FE41675E1B1EF2E090C9E162284635F3F9E412C1C846996B909917F121FE4FEE786083B60A40E74ACF84D7753B5B38E328A98203F555DC683BAC144574E5A9B0B09F7ED0282E1C7133C4D2E626F27A2827A960129571A954CBF4581E484C9D4B7540826FCD5378B557CBC1EBF7C22EB86318B3A58E460D8CEA593F35575BAA35B60EE27C6E3512E8D648B6D80ED3DB9166F4FF4AEC892B61EABFAE1527066FA081D8689C05803406FAFBC563D7B7D50344964B3A96FA3AA3DCB8986FC9FE7154242E65FA35B99852A1BFF4B4487D2ADEC6A62059891A700283696F8175F1D805F148390BA30F9A7B2EC8F0A29654E82C3EC3035A77040D192FF717D9692446F873FCC058DF1A77D1C460094501F243A53CA0457FDEB92D231B67F5BC2F348BD7BE75CBEAC05C344A9770422194F87CB36290ED3A6D5C2F793D82F9EADC940F1868AF4B5D40E4AE44F7BEFD5E8551763945A19CB734FD19C7C33F1E1E587C89CC326A9D577ED83AF8AA358F08BA8740C4A7607E6309879257BE3C28F7E455E54BAC25F2A750C4EF89370BF3D22C1C268A5658AD549EBB3D500FDB5EFB67CC1C0E0179B2A92487C83406684D110A05BA7E42B8F0670DFED89AE3175BDEDE6285A47156470C276F611DB5C5485AE19F2E5BDD0F7AE4C7D7E9B9DC1A20255D5AE205937A0C0AAD448D018590D2D73773D2B07652889446CB4110CF3BA8A67660EC52DBA3ACF77AD8CB61197FB327C50969A4BAE7E1C567E4A2E101791ED2FB4A1594DA62A2DAF059A79218BFA512E063E39B06869118CE92EB2DB978402D9840AEAAA0815F46F913F80D8ACAFE4077F09C7A86B8A9F95AFA2FA234B494F0BDBE62EB275F9118CE92EB2DB978402D9840AEAAA0817D7B82E550B2AAF97414B9371612C339D2FC624B8446E010155228FCB6F013741692C99E51783B6A4C74E9468B3D22C8532A8D2E89B718C467E54B152401E3AE3D48CCB08722394F6C3F92FA387BB30CDE566D5B0C654CAAD9094D2997D38707DBA1F34D2E86B76E665F725FDC445E7CF8E68FAE2CBA5A887993189FD5024A91BD83A679A01DF8A425CF9FE85DCD7DB3EE6FB2A067A8FDB88E937BE5269206ACBED470AC6AA8591EC72AF84EB82BA6957C509F3BC280C9D4F6E18633433BBB0EAE3C23C01FB9626BFCC0B93A45D7EA6AFE9F5EC69F089746290BCDC6B889079474DF112181B090EFB0CBAD3B5874AB76FD5D7F550A784090FAC8841D464CEE04877FAD49E75193D04DB983A954ABB64ECD8EA20C8C5B0CA47C95B79C876E52C9A63A5A6E42734CF22E3FB62F5EFBF7491C0CDE6484F537D898D95D108A4A0AF9AA3CCCD0CE01369D8E5F15757854BDA1E1C8B2F7B06D339FB38718653D352F6A9AD791A057BDBD2FACFB606CD8F1B6BBECA6E384E67956633FD30C1153715EABFD983FF6ADD0B29B311E83F05E311066FEB942A9D92DB2B6466463C4951873C5B98DDCFFF96DE3FD7E6FF153ED1107301751BA0CA9B92D66D68A4C209048AC688565EA5538EB8A850EFBB2116C3D13D4C3D44D60451BE14E6E2D47BD24F25C3C4F32E5BD830545DAAD67278E0BD151982BC25C6585181290C7CB686D101B55D4C36226021EA0B7D19D671C70150878FD9086795329C771A6B5202C76BABDD3E373939AEE46D891AC09A4885284685A90796B1E3DA316321E73B2C84BABDE10E7930322F8E5826F8C190CA0E2C26AB733D4EA70BCDCAC0CC5F3E3480BB20CBE7BCC307BDDA0201A71C4C2C8FDCECD16C33DCE3A7663DD5E7A71BD024C5507CB14AD70F9A184E23DF02E222B579A21F51D3FDD9CD220F279074BD409DC74250CFD036EDDC7CC22156BBE4E9F2A39097E2171C084AD4D8CD202A133486BA5105C162059891A700283696F8175F1D805F148710291134431D15702D6861338DD5A6E7F91702EDA2B7D88D736EA3B5CD9599A0DE6A2F200F050CF0880C9D092EFD9334BDDA3913B7D8D2E724AB88EE96B97B3C241D19091565023D5BB654E89598D61DB1B3F94DE628CF5D4CD058E8602C8B12DF0EAF355304C0DEAA4D6C34F9F2C7F5A0587E3AD957AE120B0E4C30AC434ED7E2E6DEAECA3C502FBF573DFC856F3DE2C4155681AF334978090535ED8EEF66A9979F5B7227493EB335B836B5DDB0A332D849963ADFAF82F4FEAFA747F89ED33BA7248E099E474F13ABE4F7355E3661D2FE30ED31C4FBA9C5448D026121B4733ED1304AC60F124F372971A9407A37E3CE2B9A1EEBCE1A42F9E02E0CB1BCFA2F8AA507EACA8847D09BB64B30AB86F5E7A2830A50B50AF20DBCD0370F9286B942769E51B324B3D1963163D6576740F5021BFE081309746B8CE8721265CEB9267B6A6077121FB3B38CFBB908C39C8B40A0C493BE661FD95658909AF6B825053470BB45526B10EE3245936BA4E4276A8E2A01DE832D59AEEF3D84712F4B90F0632AB5BA0652B25D49A308FB06C29AE1F3F3F7F4F3894A81E0B3CD487F68D56ED3844CD2FCC9D208E0B7CF03FB95C09DBCDB1CF7C727A6332F5D3A41C7BF7EE1D267F60FD900211B4737A7345EE80003AF8B5843882AF006A91DC9EDB22170639012F0B9FBE87408EE4EFD94E256AE44B178F00971569FA2445428616D7701F4F303A803C0DF98B6313D3A376085111AD6BE9F98965481DEBF4CDBE81A662557E462F4B8BB7B95FDA36BCBEA490DD7BEC2D8E4C2E4FF0F500B34D82849155347790A763A0262EB5C0B10288B020241255290CBC39EE01D3C8D108F59BB936BDD8F2A82DA5689157FA44BA9B6B302169EE573E66D93654419EAED3CD626905DD77F178AC394BEEDF43723F3CC60E77827AFAFC7CCD8450B6E7A680CB3E2CFFE05B7D5B5B039EC9D39405030052F78AF68972E168923302197F5C1313A29022991707EECDFD5245988934A50FD769BA2FC9C2018374ADB90888155BDA52F280D1C19ED98D0DF197EA99BF15EED8A270C8668A145C2E9B7F5B8D6D3F9E07908519CBB1F58FC0B4E00E1348F69CD4FCAB62585B43587707B28725A48EF5AD8B35ADDFBE0C2E84CEDC518D0F9A9FB24FBE68CC296CB93C5408837934DD9D492D989DCC669563DA0B757A5A0DF78C4D42DC18D76BFC35207CDBD322270493FAD01D50021678E251390A364FDF03FBE0CD9C9FEF5C161EE58854E27E51924083FC38C06C45BE0ED27345373646FF28992121329C857534D74B014352E95060B8EBD533D2F2D14C33FA2288C8286358689FD4989B089EBA04B8AB0CDD1EEBD3B477B0E39CD761F16FBBCB7CF4A9D83A73D6ADEFAC1B3CE386DB4B71E438D8E9662C0F9BB4B0AB6A132CBAF3C9B6EC08DC62C37CF2150F8A1A1283A8C40396AA935270DC868A51CC5580D5064F293B939C203AA4F82EB7C8B744F091D68223EC42584CADEC7D6B41CEC0910AC4B7D61546F4B24825AD32254F1B48EDEDCD762D9BF980BCB6E4012D8ADFFE29A6839BF18557C7FE4E5A28D3DEA7CCCCAF48246E29D3CDFACF584226AC8639318B98CFCB577B67247FB9496FE6128BF388AB5F8E4869E70110469D297C5194A32A22CD9007F6CF269EE5AEB92F1D462D72D26F9FBB4AA7FA914D5E4998614C605F3CA8D3DA86D8E4F86228A469929EC20F5CF8E82EDB8858550581942BF3BA3096107E41FB66EFF45EC3FE5708D5B2DF000530A80E72E8FAFB4DC0CB41CD2892539EBF11C7CCE918CD2529CF35A47AC3F384BF3D0ADC7CBA41725F802D3B05A145DD9D3E9E69CA69978EE47FCE294C68BD611B87AA7127565EF89A6713D583C295B3DF8D5F42C9D4E4A90EA3E7ECAEB7DC4292897ECF3A496D10B4AFBBBDD35AC46AD59CFF0ADAA99C2020A45257A87D4E4FD61061526EDD0D556CA195BB0D043D6099BC0600F5166F58849FAB80FF8E7D77B9E8E0DC8F958A07E309526C6A79F80C2779A9CE4D2EDF5A0AB0886510C5F68E01F2C736CFD8500EBD56187CDDF414C35C7E6A9AA9DB75D613AD579E18BCF416C13BA7B2526FDEDD4F0684412AC8DB5695D858162A4DED6F32102EE1E4A40D8E5BFAFF88A75623B5CC9510C4C53FAAC04850E605F4FD8DDBF81A04BC57D69613D16B83C374FC1A7EB3449A29584B6DF7A05F5F53F599B6BB05D0F96E671DC2DF943E6B031769706A92F73C2C737392341E15A3D5FF9994EFA4F20C0FB8120DA1F2659931E5264F3B961E4C5583E54EDFAF3C639F2ECF6704BD3E4D6D1EF5E822576636482C5E7C3ED6BEB67E1F1C7099DA9D14FC6431CCD1DBFFF96E1D1553D81F4C1E9F805D7D3FC67FFFFC9B1D8E3C8A6707F26590FEC1288356D053587C08DEEC0F29DCB4C7B3027D67027B5AD0A16A16371FCC0A0836FC10A386645F32EECD44E189B9F860C7C27466AF154C169D2393850BD6FB7368A6BA807A2790663255790006FBAB132476BE7351259DE171DB13C33A95F34DE9218733D2CA358CA0354E745BFDF07F1624878D5E2EC6958C430B093FBA511AF5D1599C421FCEC5624C3E6B025494CDD67328A3E7ACF189A894C81094ED0DD26131311B5E1A2DB1E7665F631AE4E9AA87540D0D03CFEC23C18FC0E8CAC8CE7C57065D1BF1DC9D1DE9B07A83227481BE92C48F37CEEF579C7F48C0536F634C64EFCB6F3801D8DC75F1C203CE49C9FE47EDF0A0ED6F5A322AF9F84CF7F89AA510B621F54C05FC30F53163D15DBB14767E4D14FBA76E28DE123041E9F5A23F9F2E705C59971F62E9B2D4D0E4C8B4552B8BEA499C0A6607D21D93CCDD540F16849039C78E5A44C55DBBA1AEAABAD700918BEB5E134C3445AB953D2585E7F5811640CB4C64FE0EB310AE6D53652D5C6F9081356E69AE9B29BA30C5E7BE59B776EE45F2D8B3FE517178F266DF5DCE2BCD4C097EE1F1B72F8808664768948E7D8426B9CE17F1B1D22A3AF0E4FA1DD768A5E641B51D0CBACFD3030585461A6ED99A3451A6E2C415CDC760E7E1A3AEE6BF0A2DEED6DE7223EE46D6B45A38B22DD5FCFD4D474322292522E3BEAF7F48F31339A4C81A21441AF438A20628FA55BC0802BD70B1700C541E357FD2F6F00961921CB0E8E9CFDC80C3E9F9EF6227D1F7A02414530BFCFEE950F2D350C7C59A0A18E77FE8A6F76A528CEBCC04A409F73263BAF858AF8A7E1A4FE63E0F14F6B22C15D4D0370C93693D12ACE67645EB17C3EE378C3F1E00B3EAA675DE35B9EC0B04352A1A672FBE52C00258464AC42275384BF9F1057876435A9276E3F736E3AEC7C19146F71BB87565F519A63EBA44FEE1CEC9673ADE2E7E5E394816798ACD2724BDFBDE93BA190B7C6D308205659C0EF3F0163AD42596C39BBF8C92BACCDA7EAD63DE7C68A072A61FCA33AB0EB533ED4A182C4B09A7EDD439C4C54F0F9D59D24C42E767A5053D7E12148ECD0126E5F77731B4BE6F50DF189A74A4927CA038C8B3C269E61DF7E5A3AA93C0A572AAA218988F5FF8DAF042F7A58CA36A069292812F8810374B768EDCCFCBA337AF9C362353942243146BED5F62921A252C378B5F9B41B6934EDBF6ECD7123273818276870CCE45B81AEE4C971FEC69A75249626821F05651786E952F3C533F525FC8B7B5F6EAB33C320532774256C42C01B7205AD6265ECB324F364F6785D5D54BCDC595B252BA48F4933C74F262A680E908D6217F81FD778E240D7ADD32B568DD00B1A2FCB2CB70D39CD39632D4883546D2FBAD0748DAE6D34E090694DFFFABF7705237947C6C8BBFE827F97009544A56B3FC94F67A972F2C5EFB19748EFF9B8ADB783E114470A7ADBBD1595E490846DF2E9531BEE796F63A1166850BB6B1FC2C14F429282EE3AD5B213835E8445F50C8711E06296371F912EAA6CBB756BEFEBE373FA80A7CE147BCF84A12E39FF68EFF2A0D40F44A304D170F20D49EE207611E67EC1AF24C244C49F842039DEB0728CBBDBD50BABB546CCE699E32FF668603387FCA38ACE7C89BB8BA142F52706D6898888D6BF4F99999E0003FBB62CAB4536B066517C8F7D022DAF488FF6617304B96D9CF3D45C1845E2443C59C3A6F6B3ECB173E9F193421AD77C449D96218488343F9E7AFBAEE2139078547CEBB62ED5FB12024C936E9D1F56C1852B392346F3B92219D09CA83E89F7EBD613518B29DCE4BDE26686F75617CD7E7690BFF58D520B16D87F5522F4F8BCBFF808BBFCDEB16CA08FBC9E71104E2923602D027C1C3B8AB9EF1F550C138970A9C21AB3A416A23BEFDF57D8091BAE54A636CEDD05596901D581308048CF77C5A0270D8AEEFCEC454CC1879C0B59C03AA4A2526DB6D3C2BF48482C8B47969C49E480F11ECD54C6A121CBBF1EEEDA08DF309F919EB484C1718CC373C8F29E9A8DFBDC3A2B64E3E3C91B5E5819F7EC4F8EA190F40374B43CF65D8EF9ECD2430C171123CE4FC643D3B1296A8B35DC8F29C4939BDA0D6BA4E5681A0304FC0B131D9CDD4E92FC48AFA4C6771F34D762CF151616F7E44C00EB5A553144FF3D2214DBFECF85205B8E060C4B7A9039A5A99C62A2C95B5FCCE42888BA45EC5FB1A8E6D7C49786445552370E45116E7DCA0129838B9909648A6F20EA06315FE643D660DAAAEC5167B5C204AECE536812E798F69E14F634CA9EFD711AC7B1A887DB433AAF6AB84BC2650ECBC864894B6B01413530163B9A0E0C93E7D67CBDCA1AAC561A35E4605BC37B452D469E01BBAF52CCC9E08329875F1558D7293BD73D7992CF3FAE2BA844CB4C3EA1BE890375ADC66CB1406E6AC043C02FB6CCF652186E8D6A59ACF284C0A4ACCF7DC8F7E57A94E3321B3839E2CF469EA737EE6E8980549B76829B29234BD5F877ECB298B21DEE6B37D5E46CD3403AC854FAE1BB3E08DC7096491F6CC7BB937FF4BE3FEDF68CD6538745BE7E760FBA1B9068DEC40641C3F3897DD9F90EDEB78530F6474539A9F61A0EF0528BE905CA2A512AB8B3E98CA0F0F7860E14B9412266F74B88CFE88A99935B38C4CC18BFA4791CD3B5575005419528735F9DACEFB259D167C250F782FFED6992436F35D8BAC8DA7BBBD8BB525F614A9CBC54CE98DB4367290035D15E957CEDCE9C84F52468ADD40F1788B45792FBEA514FACE15787C6DF86867A7E9BE693DB1C8876CEFAB16E60AFB71D66693D046C0C7ACBF96FE51188E61F63289DB8D1FF68FAD8E979F44E9C4907ED2DD3B9A11C23B1E7D472DCA16C3117E29333C1559AAB77B6F8A2928F9CA8D8677969D41668D7FD849ECC63EA7887A097B957AB6A2EFED953F2401402C249863E1A48015763F426CD818764B87A5EFBC29FABC1420FD78852A1BD727A634E2D7631B4E8D13F653E9AE9CAF331C27179E42233EDE93BE998524A329BEBB41E16943FA0B425B3184E6D756DAD71E4F185A601C5AA07468CFEE447841524999292C6A366EAF6525E276DE21F2FAC66F938015652AAD176419143762FC7C8C67FD0ABC69443C5AB5728183205B8C4C2197A9FD0EBCE2BCABCCB92ECE940534C4308E93F3850072784A16D4AD96220C1E824EF9053CCDD76CA78D834F1085D91AF9195A029E1E7445A67709E9EE2919DE4BCAC1C0FD2126A432D54E8736BA51CE906D9B784F43275F88E61B5E05A488BD7B2613E38D832166F4D236136FF3B88D0795B9937667F523BE902BC11604EC956A00CA3EDE437DA9BF9EF64C8F2288E92CA2B72587FA01E0E09D4AA606C8BB2F92CB9AE4C8753E910716EE44FC3DB7FF5884866463B0D0264019B39C4065CAD037911A44C0EF78402497E3CF7318F12FA666F555511A68AEE13448C3D7AB7E45480DDC241E0CBDCE2299E497382DFC84B7E455965CE6F9C9B64AFDF6C89E31482A0844C525AFF963280D1E00B4DB9079EC897E3DA2AD187FB81006F09E35E2A00B7B5DDBF6383A0F722233D1C8EC17B17537CA446CB9592AEE7CDB6D76C9B56A73E0B90C521BC745221FD083800899BD6CDF33ABBCA54235C522A744EF6F3A990853958B0C8C25320E3246BC43691379018A93CA28F69FE315C20E583C58BF0748C4546D89760E314F2E9A3222D641D6B4B963E4949F5BF278A1551BE72B2565AAE225D877EE56409CD9DA5D0CAC8E191822623B4E4AEAF5FC3E3700096E0C5942C3B97E65D138AC6DBCE6D8788535100CC0089017545E5697924F3A0EC31FFBFEB19679F1431DD0A607F173DD466F98266B1248D425B7E32F0360047D58BF1340BECB1126C3818DA4360175C6D7D8CAD5FCC1BCC9DC36C4E74C4FDFB70C62A98CE75466278AB3AEA9E6B79D16C4C75432317B375417DEFFD5846584F0AE5B05ECDCE6C99B3A03C216BF45866B1EC12EA0A5F7587C6DE1C497A2E08B85F385B71569EDBD406D93B3B1D0DB2E7F557561CD36E737C2B43E298AA9739004BCF55D7C96CB1438F2BD7BEABAA9C64B58932AEA808BBDF30FA4D363DC501741CF8A43AA1039E7B46576B8B299AE300E7BB49B61FFD29D0F814857931FC2AF69E6988F12C6731D619C20DF1D7096DF5C656C765A35DBF099EC5AD97B54F5A40128182B0508A6C5E6C7BBE9958F290D76637909E4759AD778E6924255A7AE038296127F00124B51F5F3742475E68C2BA4B2BBCBF39CE7463999A2C95569FADBAE6F80CC073BEA063CC5587D9DB5962C9B392E6FCD143F95EFAB1F619EFF7FC7CF64FE3D195916CB53AE2A956880EBD9EB199B87E5FC55D497FE261DE93C129564E90DF1BB21DCF41A53EDFD430213C35BF4D85E860C04C06A7CFE8126CE520C1286A24D6872949B702F09581F8351658CB86D44C1629B4A0F24BE07CCD39DD21D9AB8DD1B082462AB67338D0326B481CB4BD541D25DCAC6FF5A98AAD4B5C6B50BA0F7177C4D40964B46E96EF198309222D50005E1ECD5458C71473466EB2693B3EA732309B19A3EA582099C4A16BADE4850097BCD495BFE8DF97E1FFBBA29638CBFD8D841549FB213EFB29AEA862D6AE28FD152820CD0AB67965C2D08956016C4DD6D24F94BFCC9A396BAFD26AC085709F5899C4A6831E8DF072A96A05DD8B854963BD0F2346F13E5FDB7050BEB13B4DDDE99B2A60BB4550129FE53E049CA595351E29A07CE7828F387468AD313E11040C3C0C2F42DA056A311FEB561DBBB9910F080485FE31B1A3C46D44000BC619C578B387C7521E4CB99000AADAC71BC2FE7CE8EBEBD9EEDB294702EB294E0E2CF639B6766C12416A3EEFA84CE71C8D630851B5FC5C57F80F92A119F07CF623DD1CD80988C7CE6B6E1688EFC9226050ED3494822309E2049C0ADCA80327165283C8C8028769134D9FF9DDC6769E4EA422C5777215EF7006B8EB54FE5298D5386EC0AAC906B03C5E1180C5E2AC69E1C93053DCC41921E66F976CA35EF242F2A26C86F311F7B998BBDE5B83C547B4039F44B0DF8ACFD24F2928D4CFBE7DB647ADB1FBC95A7E2DB518A5A370D9A74619283F4F77F159BF5CAA1A489631458F8030C645731078489A144DF87BF847318F420FF5A611B4AB8D7E3E4DC2DD74F3C91E7ADCA32E4D4EF99C0410664A32B50A85D2AF82006C859378791E86DAF7C94ABC34C166B9AD0EC287AEB8F8E275E45C51FCB7EC3EC5B65668A07F8D8DCDF19F201DF1FD0134B3309212EA13CDF3E0A25CE16201B0A69C2830B7AE5F7F8A95EB38399BDE01FFA81D642147D2686E56C213C42F3866445F567252A47A95AB5AC483F2BC6C9E269A9F75349768567159BAF00B0A5809ADA84870721AFAABC61BB2263167D70B916871208C64794C929BDADA24D89393E40747EB6F5E4316FF5360AC876F726224F5319332B90CFDDC2AF9F401EEC6BCC002940EBDA36AD04905B209DCAC11C943DC58565D53E260494E7A3266533A0B6B98D21D1AAB449F08981B01B2EFBAB0ED4E7126E54ADF47F5C8C45D3DCF2C65ADBC8989FC7D5263040CA402B76897811D409D1B04A0C80A078ABC9C4567AAC088F1C20210FEA960236D485728326EE3515B05BECDDE2D1FDB5549260FC023A5BA9BB775C14001F88A4C5B35BDCEF9858BB8660D1ECDB0A780FA439E5E38E96BF36C1E97BD80CC0B11A704EB2A73A2E6C0495FE780397C157CC378F2BFFB86014DFA7774B0558CA6AACDAA5D29CBCEDA55CB321D2B635EC312BDAFB30C45C006D8248D6F8F80D037EFCF94692F5DCA16E244D665DDABEB2C39F0011BD0F624E30D2F6853DD46DA56AF67E51D0B34C9D075F5BC3A90393FC8F5E96CD8E029A7901191E66CF79D64651CD6B95870F483A39AD9CFB53B5D1C66FF7CDDDE4FA42405350DAD3B010F645C5175461EBAC27731FA4466461AD472A0F37B531227A59AAB687D14409213EEA815AE4F925BFAF43276947B28F965F99AB15948FE8074F7130F929E481041DC9372B7B249E1B8A5AE6FEAE678C1DDE54520167ACD1CE98EB678DDA102E7F3B8B432228EDD58AE4AA4CF9A24ACABE95DB1F544421B177E30F32443B8A13732A45DDEC167958C4E7A35E65391C59617EFA7E4A18E0BFFF6ED42A494B070D7298944A7A2654663BF1BE91C73F023B6439BBD4368A191E1B31B4229329E2E81949E46F2AF68609AD9A72DE6F75FA4725A4B50012BAF07F460B04FEB6B15483EEE459135B6EBE5EBA62493F23B4B046F1D712FBEC4E9DBA3FA5D0CA2DBCFCDBAC154771B39385F0F0834779D6B35F888FC881A47BCF4C074FF9195B18685B30DDDE3899D3E0D553FBD6EF5F8788BA2E977C93551E92288E2149804A3B64743ED730D265E82534D123563B3D3311264DDFF1B884043EAF01B8333944BAF360F09FEC910F44AB8AB1406FCF4286F04C88250CE337995994A9BE19B0599307A0557F722233BA3D325EF2F2C4504ECB5C157CE80267942DDB304A4CEDAC15915639B162776C4C853B98E9B45CB12D03144696C1DC81F3EC75DCB2C0D7947683F1E39DF344E30DEEB7F21552AA6720D81ECC47EAB91988223172920012B0DA85B78F80027C3FDA06F30E60CDF1F9DAE40188F51DB83767E6550FC97C66BF183E580F55A9FA682504A86C4DC29E81C6AC3973D24731C630180AD764938B71DEEE937DB1682BBE9A4C7D49349B615B688E13F3DB8AE25439F4686217BB31974584320FAFE77E167386C6D54CD8F9F0082DDF6CEEA87673F2D1B5F15A12A8A844D2BD55E7DB2D842E456B321432C62623C4E304B20230E7837D67F4DDF293F46520BC957FD952234605126FFDDEEF94FC5E77D2013D1A49CD7020DDEBE9E8A704BADDF4EC56E2A47AC02E134BA6B1CDA80FA5A0E2530E4866C99B163C3E378CC770FA5E3855CE5C146583D3783474F83187F9AE5936FCD448BC8CB91E2E29965368A9F3B140D9DFA6E95CCAFE976A93C6730B6149CA739816C02F4EEC2600216CEECC8C14073CB6C93A6472119345BB0E0BD96E557FF284DCC19F90784E39AD0EA77708A37DCA7AD9403FDC6655A45028D0393804F7A4249D3F592998DB96950F78EA46592CC53A0C197E141F930F58DF7BE81FED9B158E3F232D4DA926135CE6CD8D16FD88C43623D13F2401587323B822F581E3D2935AF2ACF3E4FDBB682CD9E0D2C09C995B47AC930AAC36CFF6C556B94E1DA0561151EC280806EAB7F9ADD950B791B720DA3442BCD0BA3528FAD1E11997E3FE8DDD4496981630F6D664960E5DA44984A2025499BAAC975C12F57CA9F5F425242BE527C64CC062463D03F93530157A256DA1575AB97EA7528986AEA76D5B1EFC34A81B809F5979700EDC9D3BE902C28EBE1741E1F1109F5FB1BED02631FB0F25867119BC63D6443A22013C6B38B1E2231DF0C5E1CCC1B05E34917285B003AA9E13011458B2F776A64A63DB3BFE85675F8DA25C8E697D594A6F801E78EB375472F039DF556B74FA908260F1CFEEE87B938CF6ABC4717039DF7F29E31F503CD38BC3FA6441A0CABD24C7EB9685C1971EA977CC7166F3C6FC857227F04C47B239BC9B66AB1C900CBA95637A72948037601877D8AD8CA60D935C2D4A7175ECE306AFC15344DCBC568EF74EEAF981B4C28AB56B2DE51A8CC9D3F2D61B06189CDEFBE371C3442DCAFFE1C0555ECE43523C5D00DEE2C4AF477C773A4CC02CA63337489DDCCD645E6D10268083B3A148E09D4902A3E15813EA8F6E27FFC022B144454667BAA3A67D01FA2DC0F26FF7721EC6F0FC13AEFFB2F7111D181B57978277BDB694F6F34076895F91A078F2BEC3303AEF47F5EEB898164CD4D80426B9593B0F5473C6B2BB947FDDB377A957521F9417DBE4162A1A3842218EC2F87FA87D4702E2A4766B1A8D14CCE492DB85F7D028D0E77CD29CA26221E1A738376378E1D7D611CA9064D021FF37C4F90EF5CF75762DF8C79474D1CC66D1B655BD5E30AD8C0B7676E8E96F8BC155CC94584E4D5FCB1BDFCED948F8ED31F5241E591DB6C53EEDBAD4B167299DEFD4A9E7C64EAC9AE5B1BD4C0C8BC29915E7B2E0F32407040F390DB5DE243106CD74B6FD02554FCD534D9FA3DBB34133FE1AB83162B5BFA019B27874CA226AB586DB37DB60EEE066E2E71A74321D15254C8611EA500329A050526E6EB229745EBEC1B2E01AAEFA4D4A839DD60C5B5B4F41AFAAFB3DA78DFE5A3108B837BD3F5EE623D878D39AE6C77F4CCFAB9D0F572018F46BE01E0CCA9DFBDD6C6438F7240CFCF1C0C25231D72A2C48EB9B553275B299DE98D02B15075398A837EDE94A85BB834089F969C06B45D5A33C548ACA31CB006D5C7B4B2CEE7E346F96415161D79721A22A29D8B2EDC3ED99B08557F5A170BC0EBB6526821BC5DB7297AF25DE46570F975BA8B5845CC7FFA5A74C201B51A90A2293B45D77D52F90A2B9AB42922379DA819B6B54138590D7E8ECD8B50F455C492B85ABDC1042E1ACFFACA92B0CCC629C1135DF4DB0FC76330043CCDB2E26DE48574113DADFCE23B146BBE8F5C22D501778AA5DCBFEE4FCD0173BB60EB93A0796E6E2E4A13676B39A5BB5E4D7A3E292DD20917CA3CC170E12C5C933036A31D80080BAE9B45574D70B5282859401145DE90810D0DB0D6E76A222D36E483C3CD9DFA0923696B024F0D06ED83DE0E56F662C3F0884CEACAC9A95F6632889420E3E57224F43C6EB5888DCC95F14041B66096219D49B3186C94477432D47F605788B34F491FBA6657772651BA8F9DB8F469898315AF514FCFBCE15FB82AC5B2C043346B152E1632635C708D61A000E420813C3A31BC1DC1352EFD258244DC3454157882E19486D6A74DA1021A0431A2FC43D03B7FD8993422D30027183E8B2BC727DDE4AECE3DAF454D6FB7BFAA4BAEC281100C2A59D2530AE67421DF76D8E9D01EA507544BC8799DF19FD2FBCB214D3B80435B5BC9040051048B02390EBF080DE1111178A915BEB018E3EE5A43B483A1526532CCFB48221A7319EAF8AE2215C37D7A7684FB7B924D9079EDACA56BE7B57AAFA979BC20992A69745E91A3B74911D238033AD90B8C6241F1D72C1CB8B2672841F61119B5A6298D5B34213384DDD540B965A600C682540A3BD8F466AA25E75CA34883E68EEEFEDE502BA7665AEDC133707A380627F92A990E2E27874CA226AB586DB37DB60EEE066E2E71A74321D15254C8611EA500329A050526E6EB229745EBEC1B2E01AAEFA4D4A83E93CC0DD26A8D770423D127B762AF62E3F3BCA02510AA7C67E14B038F075C5C0511878324C47DE85C28C9CCF10245325D5D52717ED331EDEDBBDFCD4DC61A9E63100328197EAAA40DD8600B21E1C8AD0AD1187B69E29FA78FA7D618F7F82B6100C102EAC3DA727F9E322543355DD0128F5420E17564BA6638CD784D9E9A83814EC0F46C6F2113F35D12117F0C93948F7C789DDC46EF7842E95FC78CB961DC312ECB58ACB1EF0D614F2E9F144D464124EFA9E06148E78DEC111050B93F0BEAE9BB408392FB4506F350DB7ECBB6E026DFC61336D130B1EBFC9A702DCD80915BE21C7372A3B767068E27040CC5679158C166C159794AC3FF300F5F9E53C1F84420B692A14500F98C72FE2E52D6643D185D217CFAB3CD9EF9C41BB297F65E164B654EEC777CA127A0173197179A3003783C2D48F7C2E1B257FF189D40030776CCA162E0F130F1798BFE2B588CEFC16BE109B03BF936AC25A28785951E49DB104AB23BBC121C5D5D6BF441E2A49B61E8E201346EFDC76ADAA55CCEFE4BAA25C540483096F36D767112B16009FBF74708EC3E38982DFE9B31B75C09B524B91E64461865BDCAAD85445D208E013874415964E448929D746C1AE26A6B932F919577F60E836BCD7937E677BA4D8134820696116850AB81F22EE3691BB4F306FB9F4029BD87D3C9BDDE5ADC1B3578F099809A8FC88BF3866E9428B6DC2FA66C8FF172A1283B3FA3D76561CFAC53DF900A895DA44CCC9A34D99C46C056243CF601CC3D2E300B32F60C74E739932A2F2CA0B2C91B9C539B885A4A33A164D35B6949BD5EE060BA28D02DF6672F5FAFD386C1CC5FC2E3AA8D1B1E91B8CAA7A2CD45EF78E822DE10B4AB0C4941DC4C01A4FC21BCA8BD1843ED0914E511350ADB4DF15E4561083C59754749A5726637CB64200BB665511F59B37408568F438D8FD0F8BD34BE5B2B789F5C733E1DE46DE6808F06311152E94DE6173B784FF6E0B367FE993993E0C3065925CB492F60F023B00423670119FAE218E54A5CC0C73E08BD6E8883F0FBB83F243868D609889B0220D7997728ADACF39B885A4A33A164D35B6949BD5EE060BA28D02DF6672F5FAFD386C1CC5FC2E3AAC3B31671BE86983D2FC361C7576CB730B4AB0C4941DC4C01A4FC21BCA8BD184BDC143E13AB03AFB8B460FC86564C5797068DDBE9995E5B798B9993DA100D94B05C0EF0620AB84CCD3DF8FE4261FF4BE168B4B471FA03FBFDB59820DFE0BB59532D82B88E154C051AAE9F7C2DE99D8F348F3682415A25EF8BB1DC0A5EF37015CAA780A19678FB2BD1299374BC9F7CD3F416A96D70D0C8BC84ADE068F1CC158D89A2073F04DE9A442482670A75534D8E2075929024AAED011EF7B27582DD1DB65B3EC7CC7FDED33037E8F56BBCE353156F268D9BE25F3982EBB4731646FF7E5A2854A243B2381D6AC9A8B3C40476B25CBCC362DCEE464C4099972FD4A763F48D21A6FE20FD68323E6DEF620F656CF28E41D8E14E6438405C2B22728B7AB9C088E413074EEDE5E07B4994CD2049A185678BDCC0F26D406900C223E3D3D73966F8935A072AFB238380778EC85DED3E9736DFCCF9C7A402173B8C5C616CD8E7A8EC8B9CC837A6C7CBBA15E62E6C50A7A828FA1C0FC246AA805F1E4CA1B6FC1138CB35211FAD88DA43E92D5C73201AEDD60B54F5E5F3875B6B412B6ADC0980821E0A16DDF2202C2097C974C14BC490612D356682CE5CF702E6CFB49F4F8B6318322DECDC96FEDD79B47848B2B517A6A0A519C46A0F17A81817F1E50D36B94BE0A2D1D018602B2645F3C0EF839BF2874DFB5AB6BD5F8B4EBC52574E2E6FBBFE698523E6F84E8906CEB38CFE07B333AAB0DAC201878E9171BB0EB56A753E4FDF8A4504241484214D578263A3DD058187C4EA24ABDFA707BD1004A9125CEBBC8913F250CCF4EF4AA2D4B89D689CC8E99EA12BE553B8DD975350EAE6D121543C13BD03DBDD57ECA97C16E6461C710CF4052B84C5821BEA529C55227F401E4BA9EB584C7EB26648AF893F20E3C73E038B2C76DF8C2CF35EF70F55C25CE8F59EEED9164FDD8C3D453708E101E456346123448D658C94C0869AB7674CE7EFBD6258F1FEC412F8941F11017D143F2C4CF0FCBC32A3002C132208834E3C52CBACA4AED32A44BD9B515936CC0394704099B511F18BF3F35BCDBDD1A76E49A45DD5DA51ADB54014B3284BA7A5BB9A69A60E35966EE12ACFC9780CE7EA0CDF220AA0E3E7FE30E110704BD91D2E08EEF33345845CC663BDEDE1801D04A682119B6E7184BC8EEDEEDCE8F8D62191BFFDBF4852356845FDBABAA4FF5809935FC86BD21360285E6F6081AEC6B26EAD2CF3B038A05381C7153DF51C7A36B3EC1A54AA44F52B80B855C90167BFA28C21458F4715EEEDDC9E43C5D9C23668C7615484FA19E9643032D91CD34E8BDFC213DF36EEAF780C444E50E01E9AC6804CFAA9F2E0BB0115F7A16179A22D5853C765B6A6DD59F2393DF15051182E6EF1700227477F25B4F74B99D0064AD68682D5120D932D827A4C795468440BBED354761639E22B305346FD74EA67E9D1D4A6F4B9F08ED159A62A976180874940B891E189B2412190C85BD0162382767EED017D37D9AC7579F3136D3D38DDEA358FC0D7DA7E2D81AC17EF82DE6BBE5065B37FA86470F50933A143841658747F47779B3C321E4CE4C22363C3F31F2196B65DF63C56FD9E2EC886CADBEAEF65CC4A8A00EC3792AC5FF6691EA37CF4B7C7EC938D0DE37CE22A11E186C13299EA4803085FF7BA0771D7B376E5866FD45B64B9045936BA753A71E2B10FC7B21579FF84069562AC291E11D35235DD45C87A6F7A016F9C24F7D60C01B7E101155C90F0D3808EB0528FAA080769E5E3F6E29F7C4F97626E202A32C47C7F62732DA5BF0B6F492F4BC56550DA1A9371BBBD7D0B1F026BF41573CD2EAFF09884CD0071BCCD5156F849FE6F8545CF58F14B969520ECDA988E531A36CDB5031EAE88850E1F33C4FE43E61B0482AA0B198EF0194EF383ED964DF673FBFB6096C0844087D47B39D57ECE891059A623AAF24921B9BCCD56818F43462E88FC0415F58370CFD8C9087C23304AB7F39B3E1CEF3E035B93AACACF681610BFEA6F41FBF1A8D0D18E91252E938120EA579EE755F8735AE26E651670D344A7178D0327166931E90B35D1ADC9F583D225B1001E50CE8B0791F2E02FC1A2B5631D9D27A79F2E0DB0073CD029F40A2D73AA495F3F844CF22B1C383D70C43D90530F59922BA8D297A3B38B92C21321AC900999094B6E49F5F8E67E8D3986A8D6B1F7F31507288508615F0EF11143344A74B798845BCAE5C3880E01014A37FD18A1025B51A3EADC8A927A52571A2845CB71AE284A8E4802BE0B8944104E858CFDEB9146634E9A40DAF7E7CF3D3D4319C9E6B0D2B0ED90BE7EA0AA987F8A58A9D5BB6B36FE0A6BA8F1388CFA586376672795FB3F22E743C55F099DE488217F97A9BCDF74289975DDA109F0A7530D03AEC15D57DA947AC0C653EE57887745655A5DDF88B9B40B8C576F244209047F6CEE2A0E714F8DC883232E283F9E217C6E66AC6AAA17285BEA81B15DCC5872435720C2E462F1127C3B41BC1405B80FFD4E3B5C652DC22DCB3BD0389D7E2D2168208CB590EB7302FFB1EFB037CEB53E5D1830507C1572D6110161E921E6FFC49DB4445DAD603FB4E83220DA450CB9EB4D988DB3AD6C9D36FD7D50BB8052DE49AC9B174098FF92189817CFA066D9A4098ED588C45148A54D67F8DB0B0C8A17FF049AA87EE8DFE2F4F8B7284CC0E041758F4419C11005EA764B84575FB61CE2E09EDF2BEFD4BBE5AF2ADFB2437B10717F396F899D3E30431779A2B492DD6B578B9B458A8B11AD1E8DFADD3834DA854FCF95F81C4FA2D8F96D3E4F860BECCB4C2C3D10A6FB7750D09D4DBC28FEF753B16F536C5FAA942D7C30B9BD0BE62AA96DF892EC27B8B16A54947441C30EE4E0180A19E8FA094D3DCCFE591ABA767AA6F7962DE2E2373DD45C3C88A7B2915 \ No newline at end of file diff --git "a/spider/js/\345\212\252\345\212\252\344\271\246\345\235\212[\344\271\246].js" "b/spider/js/\345\212\252\345\212\252\344\271\246\345\235\212[\344\271\246].js" new file mode 100644 index 00000000..55c284fd --- /dev/null +++ "b/spider/js/\345\212\252\345\212\252\344\271\246\345\235\212[\344\271\246].js" @@ -0,0 +1,136 @@ +/* +@header({ + searchable: 1, + filterable: 0, + quickSearch: 1, + title: '努努书坊[书]', + author: 'EylinSir', + '类型': '小说', + logo: 'https://www.nunubook.com/favicon.ico', + lang: 'ds' +}) +*/ + +var rule = { + 类型: '小说', + author: 'EylinSir', + title: '努努书坊[书]', + host: 'https://www.nunubook.com', + url: '/fyclass/##fypage', + logo: 'https://www.nunubook.com/favicon.ico', + class_name: '玄幻小说&魔幻小说&悬疑小说&历史架空&都市小说&言情小说&武侠小说&官场小说&现代小说&战争军事&侦探推理&外国小说&纪实小说&诗歌戏曲&宗教哲学&文学理论&寓言童话&科普学习&社会心理&作品集&传记回忆&杂文随笔', + class_url: 'xuanhuan&mohuan&xuanyi&lishi&dushi&yanqing&wuxia&guanchang&xiandaixiaoshuo&zhanzhengjunshi&zhentantuili&waiguo&jishi&shigexiqu&zhexue&wenxuelilun&yuyantonghua&kepuxuexi&shehuixinli&zuopinji&zhuanjihuiyi&zawen', + searchUrl: '/e/search/index.php?tbname=bookname&show=title&tempid=1&keyboard=**', + searchable: 1, + quickSearch: 1, + filterable: 0, + timeout: 10000, + play_parse: true, + headers: { 'User-Agent': 'MOBILE_UA' }, + + 一级: async function () { + let [cateUrl, pg] = this.input.split('##'); + let list = []; + let cateKey = cateUrl.split('/').filter(Boolean).pop() || ''; + let cl = this.class_url.split('&').findIndex(k => k === cateKey) + 1 || undefined; + if (pg === '1') { + let html = await request(cateUrl); + let selectors = ['.listBig-li', 'li.listBig-li', '.book-item', '.list-item']; + let items = selectors.map(sel => this.pdfa(html, sel)).find(Boolean); + items?.forEach(item => { + let urlSelectors = ['a:eq(0)&&href', 'a&&href']; + let url = urlSelectors.map(sel => this.pd(item, sel)).find(Boolean) || this.pdfh(item, 'a&&href'); + if (url) { + url = url.startsWith('http') ? url : `${this.host}${url}`; + let title = this.pdfh(item, 'h3&&Text') || this.pdfh(item, 'h2&&Text') || '未知标题'; + let desc = this.pdfh(item, 'p:eq(0)&&Text') || '无简介'; + list.push({ + title, + url, + desc, + pic_url: this.pd(item, 'img&&src') || '', + content: this.pdfh(item, '.text&&Text') || desc + }); + } + }); + } else if (cl) { + let apiUrl = `${this.host}/e/extend/more/lsmore.php?page=${pg}&line=10&cl=${cl}`; + let json = JSON.parse(await request(apiUrl)); + list.push(...json.map(item => ({ + title: item.title, + url: item.url, + pic_url: item.pic, + desc: item.smalltext, + content: `${item.smalltext}\n作者:${item.writer}` + }))); + } + return setResult(list); + }, + + 二级: async function () { + let html = await request(this.input); + let VOD = { + vod_name: this.pdfh(html, 'h1&&Text'), + vod_pic: this.pdfh(html, '[property$=image]&&content'), + vod_content: this.pdfh(html, '[property$=description]&&content'), + vod_actor: this.pdfh(html, '[property$=author]&&content') + }; + let id = this.input.match(/\/(\d+)(\/|\.html)/)?.[1]; + if (id) { + let baseUrl = `${this.host}/e/extend/bookpage/pages.php?id=${id}&dz=asc&pageNum=`; + let firstPage = JSON.parse(await request(baseUrl + '0')); + let chapters = firstPage.list || []; + if (firstPage.totalPage > 0) { + let reqs = []; + for (let i = 1; i <= firstPage.totalPage; i++) reqs.push(request(baseUrl + i)); + let res = await Promise.all(reqs); + res.forEach(r => { chapters = chapters.concat(JSON.parse(r).list || []) }); + } + VOD.vod_play_from = '努努书坊'; + VOD.vod_play_url = chapters.map(c => { + let url = c.pic || c.url; + return c.title + '$' + (url.startsWith('http') ? url : `${this.host}${url}`); + }).join('#'); + } + return VOD; + }, + + 搜索: async function () { + let [url, params] = this.input.split('?'); + let html = await post(url, { body: params }); + let list = []; + if (!html.includes('没有搜索到')) { + (this.pdfa(html, '.search-wrap-first') || []).forEach(item => { + let url = this.pd(item, 'a&&href'); + if (url) list.push({ + title: this.pdfh(item, 'h3&&Text').replace('小说', ''), + url: url.startsWith('http') ? url : `${this.host}${url}`, + pic_url: this.pd(item, 'img&&src'), + content: this.pdfh(item, 'p&&Text') + }); + }); + } + return setResult(list); + }, + + lazy: async function () { + let { input, pdfh } = this; + let html = await request(input); + let content = pdfh(html, '#text&&Html') || ''; + if (content) { + content = content + .replace(/]*?>.*?<\/script>/gs, '') + .replace(/<\/p>/g, '\n\n') + .replace(//gi, '\n') + .replace(/<[^>]+>/g, '') + .replace(/ /g, ' ') + .replace(/\n\s*\n/g, '\n\n') + .trim(); + } + return { + parse: 0, + url: `novel://${JSON.stringify({ title: pdfh(html, 'h1&&Text') || '', content })}`, + js: '' + }; + } +}; \ No newline at end of file From c24940ed0128365be29bcc2d3f45a98974e06de7 Mon Sep 17 00:00:00 2001 From: Taois Date: Sat, 17 Jan 2026 17:50:26 +0800 Subject: [PATCH 038/101] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0drpy2-fast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/config.js | 55 +++++----- public/drpy/drpy2-fast.min.js | 102 ++++++++++++++++++ ...76\347\275\256\344\270\255\345\277\203.js" | 2 +- 3 files changed, 133 insertions(+), 26 deletions(-) create mode 100644 public/drpy/drpy2-fast.min.js diff --git a/controllers/config.js b/controllers/config.js index 34a1d68f..1b8aae62 100644 --- a/controllers/config.js +++ b/controllers/config.js @@ -327,9 +327,12 @@ async function generateSiteJSON(options, requestHost, sub, pwd) { } fileSites.forEach((fileSite) => { - if (enable_dr2 === '1') { + if (enable_dr2 === '1' || enable_dr2 === '2') { // dr2ApiType=0 使用接口drpy2 dr2ApiType=1 使用壳子内置的drpy2 let api = dr2ApiType ? `assets://js/lib/drpy2.js` : `${requestHost}/public/drpy/drpy2.min.js`; + if (enable_dr2 === '2') { + api = `${requestHost}/public/drpy/drpy2-fast.min.js`; + } let ext = `${requestHost}/js/${file}`; if (pwd) { ext += `?pwd=${pwd}`; @@ -348,31 +351,33 @@ async function generateSiteJSON(options, requestHost, sub, pwd) { ext: ext || "", // 固定为空字符串 }; sites.push(site); - } else if (enable_dr2 === '2') { - // 模式2:只启用T3脚本的T4风格API配置 - const t4site = { - key: fileSite.key, - name: fileSite.name, - type: 4, // 固定值 - api: `${requestHost}/api/${baseName}`, - ...ruleMeta, - ext: "", // 固定为空字符串 - }; - // 添加isdr2参数到API URL - if (pwd) { - t4site.api += `?pwd=${pwd}&do=dr`; - } else { - t4site.api += `?do=dr`; - } - - // 处理传参源的API参数 - if (fileSite.queryStr) { - const separator = t4site.api.includes('?') ? '&' : '?'; - site.api += `${separator}extend=${encodeURIComponent(fileSite.queryStr)}`; - } - - sites.push(t4site); } + // else if (enable_dr2 === '2') { + // + // // 模式2:只启用T3脚本的T4风格API配置 + // const t4site = { + // key: fileSite.key, + // name: fileSite.name, + // type: 4, // 固定值 + // api: `${requestHost}/api/${baseName}`, + // ...ruleMeta, + // ext: "", // 固定为空字符串 + // }; + // // 添加isdr2参数到API URL + // if (pwd) { + // t4site.api += `?pwd=${pwd}&do=dr`; + // } else { + // t4site.api += `?do=dr`; + // } + // + // // 处理传参源的API参数 + // if (fileSite.queryStr) { + // const separator = t4site.api.includes('?') ? '&' : '?'; + // site.api += `${separator}extend=${encodeURIComponent(fileSite.queryStr)}`; + // } + // + // sites.push(t4site); + // } }); }, param: {file, dr2Dir, requestHost, pwd, drpyS, SitesMap}, diff --git a/public/drpy/drpy2-fast.min.js b/public/drpy/drpy2-fast.min.js new file mode 100644 index 00000000..8d397161 --- /dev/null +++ b/public/drpy/drpy2-fast.min.js @@ -0,0 +1,102 @@ +import{cheerio,模板}from"../dist/drpy-core-fast.min.js";let vercode=typeof pdfl==="function"?"drpy2.1":"drpy2";const VERSION=vercode+" 3.9.54 20260117";const UpdateInfo=[{date:"20260117",title:"爱佬新So测试版,使用drpy-core-fast.min.js",version:"3.9.54 20260117",msg:` +drpy-core-fast.min.js内置了url和sqlite模块 + `},{date:"20251007",title:"爱佬新So测试版,使用drpy-core-lite.min.js,内置了Buffer库",version:"3.9.53 20251007",msg:` +drpy-core-lite.min.js 内置Buffer库 +gzip和ungzip改为新so的zlib实现 +内置RSA对象加解密效率提升 + + `},{date:"20250801",title:"drpy依赖更新,使用drpy-core-lite.min.js",version:"3.9.52beta3 20250801",msg:` +drpy-core.min.js 更换为更小的drpy-core-lite.min.js + + `},{date:"20250729",title:"drpy更新,所有依赖打包成一个js文件",version:"3.9.52beta2 20250729",msg:` + 1. wasm支持 + 2. 引入 TextEncoder、TextDecoder对象 + 3. 引入 WXXH 加解密库 + 4. 所有依赖打包成一个js + 5. 增加 buildQueryString + + `},{date:"20250728",title:"drpy更新,增加tab_order线路模糊排序,优化解密算法支持文件头",version:"3.9.52beta1 20250728",msg:` + 1. 增加tab_order线路模糊排序 + 2. 优化解密算法支持文件头 + 3. wasm支持 + 4. 增加 removeHeader 函数可用于清除js/py文件的头信息及所有头注释 + 5. 引入 TextEncoder、TextDecoder对象 + 6. 引入 WXXH 加解密库 + `},{date:"20241126",title:"drpy更新,优化去广告算法",version:"3.9.51beta6 20241126",msg:` + 1. 更新龙头大佬提供的去广告算法 + `},{date:"20241104",title:"drpy更新,增加新特性",version:"3.9.51beta5 20241104",msg:` + 1. rule增加 搜索验证标识 属性,可以不定义,默认为 '系统安全验证|请输入验证码' + 2. rule增加 searchNoPage 属性,可以不定义,如果定义 1 将关闭该源的搜索翻页功能,超过1页直接返回空 + `}];function getUpdateInfo(){return UpdateInfo.map(_o=>{_o.msg=_o.msg.trim().split("\n").map(_it=>_it.trim()).join("\n");return _o})}function init_test(){console.log("init_test_start");console.log("当前版本号:"+VERSION);console.log("本地代理地址:"+getProxyUrl());console.log(RKEY);console.log(JSON.stringify(rule));console.log("init_test_end")}function ocr_demo_test(){let img_base64=`iVBORw0KGgoAAAANSUhEUgAAAIAAAAAoBAMAAADEX+97AAAAG1BMVEXz+/4thQTa7N6QwIFFkyNeokKozqDB3b93sWHFR+MEAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABN0lEQVRIie2TQU+DQBCFt9vScvQpxR4xrcSjJCZ67JDGXsX+AdR4B3vpsSYm/m2HXaRLmuySepR3Gdidb/btDAjRq5dT96eCMlfBuzi1QLZUoZy2yz5sOvI+9iomaPEZ6nWnEtxqIyiM1RcAy44GNDhBXUjot/VVNweV1ah68FqWRyjKIOqAcyYF6rGcmpYnHzGt3fycNoMw0d3/THFu7hFSJ/8OXO6iTM8/KSg09obAzIHLO250LgQ0txOZSfgrV4Exdw98uGycJ0ErAeExZGhOmFHV9zHO6qVSj0MpLq7xZON56o++MjlsEgfVhbQWWME+xQX7J4V6zfi9A1Ly9rP1BvEXp+BbVJ/M77n+wfOIDVp51pZ4iBxvmj9AGrtvry6emwfKnVkW+ZRKd5ZNMvob36vXP9YPDmQki8QiCFAAAAAASUVORK5CYII=`;OcrApi.api=OCR_API;let code=OcrApi.classification(img_base64);log("测试验证码图片的ocr识别结果为:"+code)}function rsa_demo_test(){let t1=(new Date).getTime();let pkcs1_public=` +-----BEGIN RSA PUBLIC KEY----- +MEgCQQCrI0pQ/ERRpJ3Ou190XJedFq846nDYP52rOtXyDxlFK5D3p6JJu2RwsKwy +lsQ9xY0xYPpRZUZKMEeR7e9gmRNLAgMBAAE= +-----END RSA PUBLIC KEY----- +`.trim();let pkcs1_public_pem=` +MEgCQQCrI0pQ/ERRpJ3Ou190XJedFq846nDYP52rOtXyDxlFK5D3p6JJu2RwsKwy +lsQ9xY0xYPpRZUZKMEeR7e9gmRNLAgMBAAE= +`.trim();let pkcs8_public=` +-----BEGIN PUBLIC KEY----- +MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKsjSlD8RFGknc67X3Rcl50WrzjqcNg/ +nas61fIPGUUrkPenokm7ZHCwrDKWxD3FjTFg+lFlRkowR5Ht72CZE0sCAwEAAQ== +-----END PUBLIC KEY-----`.trim();let pkcs8_public_pem=` +MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKsjSlD8RFGknc67X3Rcl50WrzjqcNg/ +nas61fIPGUUrkPenokm7ZHCwrDKWxD3FjTFg+lFlRkowR5Ht72CZE0sCAwEAAQ== +`.trim();let pkcs1_private=` +-----BEGIN RSA PRIVATE KEY----- +MIIBOAIBAAJBAKsjSlD8RFGknc67X3Rcl50WrzjqcNg/nas61fIPGUUrkPenokm7 +ZHCwrDKWxD3FjTFg+lFlRkowR5Ht72CZE0sCAwEAAQI/b6OV1z65UokQaMvSeRXt +0Yv6wiYtduQI9qpq5nzy/ytaqsbBfClNTi/HifKPKxlRouWFkc518EQI8LBxoarJ +AiEA4DaONMplV8PQNa3TKn2F+SDEvLOCjdL0kHKdN90Ti28CIQDDZnTBaHgZwZbA +hS7Bbf5yvwjWMhO6Y7l04/Qm7R+35QIgPuQuqXIoUSD080mp1N5WyRW++atksIF+ +5lGv9e6GP/MCICnj8y/rl6Pd7tXDN6zcSeqLrfdNsREKhB3dKOCXgW9JAiAFYtFS +EJNBXVRTK42SNsZ2hJ/9xLwOwnH2epT8Q43s3Q== +-----END RSA PRIVATE KEY----- +`.trim();let pkcs8_private=` +-----BEGIN PRIVATE KEY----- +MIIBUgIBADANBgkqhkiG9w0BAQEFAASCATwwggE4AgEAAkEAqyNKUPxEUaSdzrtf +dFyXnRavOOpw2D+dqzrV8g8ZRSuQ96eiSbtkcLCsMpbEPcWNMWD6UWVGSjBHke3v +YJkTSwIDAQABAj9vo5XXPrlSiRBoy9J5Fe3Ri/rCJi125Aj2qmrmfPL/K1qqxsF8 +KU1OL8eJ8o8rGVGi5YWRznXwRAjwsHGhqskCIQDgNo40ymVXw9A1rdMqfYX5IMS8 +s4KN0vSQcp033ROLbwIhAMNmdMFoeBnBlsCFLsFt/nK/CNYyE7pjuXTj9CbtH7fl +AiA+5C6pcihRIPTzSanU3lbJFb75q2SwgX7mUa/17oY/8wIgKePzL+uXo93u1cM3 +rNxJ6out902xEQqEHd0o4JeBb0kCIAVi0VIQk0FdVFMrjZI2xnaEn/3EvA7CcfZ6 +lPxDjezd +-----END PRIVATE KEY----- +`.trim();let data=` +NodeRsa +这是node-rsa 现在修改集成在drpy里使用`.trim();let encryptedWithPublic=NODERSA.encryptRSAWithPublicKey(data,pkcs1_public,{outputEncoding:"base64",options:{environment:"browser",encryptionScheme:"pkcs1_oaep"}});console.log("公钥加密");console.log(encryptedWithPublic);let decryptedWithPrivate=NODERSA.decryptRSAWithPrivateKey(encryptedWithPublic,pkcs1_private,{options:{environment:"browser",encryptionScheme:"pkcs1_oaep"}});console.log("私钥解密");console.log(decryptedWithPrivate);let pkcs1_sha256_sign=NODERSA.sign("1",pkcs1_private,{outputEncoding:"base64",options:{environment:"browser",encryptionScheme:"pkcs1",signingScheme:"pkcs1-sha256"}});console.log("pkcs1_sha256_sign");console.log(pkcs1_sha256_sign);let pkcs1_sha256_sign_verify=NODERSA.verify("1","Oulx2QrgeipKYBtqEDqFb2s/+ndk2cGQxO4CkhU7iBM1vyNmmvqubpsmeoUuN3waGrYZLknSEdwBkfv0tUMpFQ==",pkcs1_private,{options:{environment:"browser",encryptionScheme:"pkcs1",signingScheme:"pkcs1-sha256"}});console.log("pkcs1_sha256_sign_verify");console.log(pkcs1_sha256_sign_verify);let pkcs1_oaep_sha256=NODERSA.encryptRSAWithPublicKey(data,`-----BEGIN RSA PUBLIC KEY----- +MIIBCgKCAQEA5KOq1gRNyllLNWKQy8sGpZE3Q1ULLSmzZw+eaAhj9lvqn7IsT1du +SYn08FfoOA2qMwtz+1O2l1mgzNoSVCyVpVabnTG+C9XKeZXAnJHd8aYA7l7Sxhdm +kte+iymYZ0ZBPzijo8938iugtVvqi9UgDmnY3u/NlQDqiL5BGqSxSTd/Sgmy3zD8 +PYzEa3wD9vehQ5fZZ45vKIq8GNVh2Z8+IGO85FF1OsN7+b2yGJa/FmDDNn0+HP+m +PfI+kYBqEVpo0Ztbc3UdxgFwGC8O1n8AQyriwHnSOtIiuBH62J/7qyC/3LEAApRb +Dd9YszqzmODjQUddZKHmvc638VW+azc0EwIDAQAB +-----END RSA PUBLIC KEY----- +`,{outputEncoding:"base64",options:{environment:"browser",encryptionScheme:{scheme:"pkcs1_oaep",hash:"sha256"}}});console.log("pkcs1_oaep_sha256");console.log(pkcs1_oaep_sha256);decryptedWithPrivate=NODERSA.decryptRSAWithPrivateKey("kSZesAAyYh2hdsQnYMdGqb6gKAzTauBKouvBzWcc4+F8RvGd0nwO6mVkUMVilPgUuNxjEauHayHiY8gI3Py45UI3+km0rSGyHrS6dHiHgCkMejXHieglYzAB0IxX3Jkm4z/66bdB/D+GFy0oct5fGCMI1UHPjEAYOsazJDa8lBFNbjiWFeb/qiZtIx3vGM7KYPAZzyRf/zPbbQ8zy9xOmRuOl5nnIxgo0Okp3KO/RIPO4GZOSBA8f2lx1UtNwwrXAMpcNavtoqHVcjJ/9lcotXYQFrn5b299pSIRf2gVm8ZJ31SK6Z8cc14nKtvgnmsgClDzIXJ1o1RcDK+knVAySg==",`-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA5KOq1gRNyllLNWKQy8sGpZE3Q1ULLSmzZw+eaAhj9lvqn7Is +T1duSYn08FfoOA2qMwtz+1O2l1mgzNoSVCyVpVabnTG+C9XKeZXAnJHd8aYA7l7S +xhdmkte+iymYZ0ZBPzijo8938iugtVvqi9UgDmnY3u/NlQDqiL5BGqSxSTd/Sgmy +3zD8PYzEa3wD9vehQ5fZZ45vKIq8GNVh2Z8+IGO85FF1OsN7+b2yGJa/FmDDNn0+ +HP+mPfI+kYBqEVpo0Ztbc3UdxgFwGC8O1n8AQyriwHnSOtIiuBH62J/7qyC/3LEA +ApRbDd9YszqzmODjQUddZKHmvc638VW+azc0EwIDAQABAoIBADZ/QGgUzInvsLp/ +zO2WbfYm39o/uhNAvk9RbLt1TIZbMFhyOpeKynHi3Swwd9xsfWX/U9zS/lGi/m31 +iKrhmaW4OA1G3vqpMcK7TBbFufYwUEaA+ZJX344euH8pIfdzyneMQ4z3Far2dS7l +QsmjuilVV2kEFadveXewiYoVOWCu00w6bN8wy2SIHlQn+kIL6HQhWz12iKKflIKu +eGRdzLHsKmBt6WbY1Wuhx7HU0fAKdlBDPxCHNlI+kybUYE9o5C2vJiaVM5wqJBgZ +8Dz8kt1QbLJ910JoLXkLVQ8uC8NJKQwFtqQjTGPnEq0+wbgz6Ij599rKZkwW/xq9 +l6KoUiECgYEA6Ah42tVdkNW047f03xVYXFH96RgorHRS36mR8Y+ONUq1fwKidovC +WjwVujt4OPf3l1W6iyn/F6cu/bsmvPrSc3HTN0B1V31QK4OjgetxQ2PSbTldH02J +NPzkt+v+cPxXpx/P5mgt7Weefw5txU547KubGrHUV5rBKFtIx9pj16MCgYEA/EF0 +o19+D24DZAPwlDS5VbEd7FStnwY4oQ5PqbuNOSbSJLMWU0AqzXcRokp8UTyCZ0X3 +ATkS1REq97kShCuR+npTR6a6DlY7sdpPI1SMLNajgB2tkx0EOzX+PfNIbHUd4jpJ +I0ZMAHv/OOtkzQHDaeTWBTrzsWm6/nTiykfduNECgYEA46AMD4HpPECqKAs66e5i +tI6q7JSKskObWVdcmQEfnSAhVOwcvPb2Ptda6UuV8S0xcwDi88rLOUUFUFzc79+P +vTkY38cYVi/VChsluDpk7ptqv0PbGu5Rf+3n4pZdEjI7OvR2W64wAAn67uIUxc7p +yiO/ET0K9rYWb6S9jXGtKMkCgYEA2kPAqoO7zZoBMQ7/oR0lp/HC1HRIbiqx4RlC +8Lgpb+QZPEwA6zPAVVvLVENi4d+bbcRp/xLlKpraNNJcJSSWAMbLPFoU7sbKjA87 +HnTPfRSTEA2d3Ibk3F7Rh8TzS3Ti0JZiJjVzGZAwu41iAMifzwaD8K6boUy80eNN +QH2CaaECgYBUsLYvC/MiYg3w+LGOONuQongoVUXjGqnw2bjVa9RK7lwRdXPUqJ51 +MpVO98IkoLvGSI/0sGNP3GKNhC+eMGjJAVwFyEuOn+JsmMv9Y9uStIVi5tIHIhKw +m7mp8il0kaftHdSxTbspG3tZ2fjIiFIZkLEOmRpd7ogWumgOajzUdA== +-----END RSA PRIVATE KEY-----`,{options:{environment:"browser",encryptionScheme:"pkcs1_oaep"}});console.log("decryptedWithPrivate");console.log(decryptedWithPrivate);(()=>{let key=new NODERSA.NodeRSA({b:1024});key.setOptions({encryptionScheme:"pkcs1"});let text=`你好drpy node-ras`;let encrypted=key.encrypt(text,"base64");console.log("encrypted: ",encrypted);const decrypted=key.decrypt(encrypted,"utf8");console.log("decrypted: ",decrypted)})();let t2=(new Date).getTime();console.log("rsa_demo_test 测试耗时:"+(t2-t1)+"毫秒")}function pre(){if(typeof rule.预处理==="string"&&rule.预处理&&rule.预处理.trim()){let code=rule.预处理.trim();console.log("执行预处理代码:"+code);if(code.startsWith("js:")){code=code.replace("js:","")}try{eval(code)}catch(e){console.log(`预处理执行失败:${e.message}`)}}}let rule={};const MOBILE_UA="Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36";const PC_UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36";const UA="Mozilla/5.0";const UC_UA="Mozilla/5.0 (Linux; U; Android 9; zh-CN; MI 9 Build/PKQ1.181121.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.5.5.1035 Mobile Safari/537.36";const IOS_UA="Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1";const RULE_CK="cookie";const CATE_EXCLUDE="首页|留言|APP|下载|资讯|新闻|动态";const TAB_EXCLUDE="猜你|喜欢|下载|剧情|榜|评论";const OCR_RETRY=3;const OCR_API="https://api.nn.ci/ocr/b64/text";if(typeof MY_URL==="undefined"){var MY_URL}var HOST;var RKEY;var fetch;var print;var log;var rule_fetch_params;var fetch_params;var oheaders;var _pdfh;var _pdfa;var _pd;const DOM_CHECK_ATTR=/(url|src|href|-original|-src|-play|-url|style)$/;const SPECIAL_URL=/^(ftp|magnet|thunder|ws):/;const NOADD_INDEX=/:eq|:lt|:gt|:first|:last|^body$|^#/;const URLJOIN_ATTR=/(url|src|href|-original|-src|-play|-url|style)$|^(data-|url-|src-)/;const SELECT_REGEX=/:eq|:lt|:gt|#/g;const SELECT_REGEX_A=/:eq|:lt|:gt/g;const $js={toString(func){let strfun=func.toString();return strfun.replace(/^\(\)(\s+)?=>(\s+)?\{/,"js:").replace(/\}$/,"")}};function window_b64(){let b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";let 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);function btoa(str){var out,i,len;var c1,c2,c3;len=str.length;i=0;out="";while(i>2);out+=b64map.charAt((c1&3)<<4);out+="==";break}c2=str.charCodeAt(i++);if(i==len){out+=b64map.charAt(c1>>2);out+=b64map.charAt((c1&3)<<4|(c2&240)>>4);out+=b64map.charAt((c2&15)<<2);out+="=";break}c3=str.charCodeAt(i++);out+=b64map.charAt(c1>>2);out+=b64map.charAt((c1&3)<<4|(c2&240)>>4);out+=b64map.charAt((c2&15)<<2|(c3&192)>>6);out+=b64map.charAt(c3&63)}return out}function atob(str){var c1,c2,c3,c4;var i,len,out;len=str.length;i=0;out="";while(i>4);do{c3=str.charCodeAt(i++)&255;if(c3==61)return out;c3=base64DecodeChars[c3]}while(i>2);do{c4=str.charCodeAt(i++)&255;if(c4==61)return out;c4=base64DecodeChars[c4]}while(ithis.length){return false}else{return this.indexOf(search,start)!==-1}}}if(!Array.prototype.includes){Object.defineProperty(Array.prototype,"includes",{value:function(searchElement,fromIndex){if(this==null){throw new TypeError('"this" is null or not defined')}var o=Object(this);var len=o.length>>>0;if(len===0){return false}var n=fromIndex|0;var k=Math.max(n>=0?n:len-Math.abs(n),0);while(k>4){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:out+=String.fromCharCode(c);break;case 12:case 13:char2=array[i++];out+=String.fromCharCode((c&31)<<6|char2&63);break;case 14:char2=array[i++];char3=array[i++];out+=String.fromCharCode((c&15)<<12|(char2&63)<<6|(char3&63)<<0);break}}return out}function gzip(str){let arr=zlib.gzip(str);return Buffer.from(arr,"utf-8").toString("base64")}function ungzip(b64Data){const binData=Buffer.from(b64Data,"base64");const data=zlib.ungzip(binData.buffer);return Buffer.from(data,"utf8").toString()}function encodeStr(input,encoding){encoding=encoding||"gbk";if(encoding.startsWith("gb")){input=gbkTool.encode(input)}return input}function decodeStr(input,encoding){encoding=encoding||"gbk";if(encoding.startsWith("gb")){input=gbkTool.decode(input)}return input}function getCryptoJS(){return'console.log("CryptoJS已装载");'}const RSA={cleanPEM:function(pem){pem=pem.replace(/-----BEGIN [A-Z0-9 ]+-----/g,"").replace(/-----END [A-Z0-9 ]+-----/g,"");pem=pem.replace(/\s/g,"");return pem},importPrivateKey:function(pem){const binaryDer=Uint8Array.from(Buffer.from(this.cleanPEM(pem),"base64"));const importedKey=crypto.subtle.importKey("pkcs8",binaryDer,{name:"RSA-PKCS1-v1_5",hash:"SHA-256"},false,["decrypt"]);return importedKey},importPublicKey:function(pem){const binaryDer=Uint8Array.from(Buffer.from(this.cleanPEM(pem),"base64"));const importedKey=crypto.subtle.importKey("spki",binaryDer,{name:"RSA-PKCS1-v1_5",hash:"SHA-256"},false,["encrypt"]);return importedKey},encryptMergedData:function(publicKey,data){const modulusLengthBytes=publicKey.algorithm.modulusLength+7>>3;const segmentLength=modulusLengthBytes-11;const dataBuffer=(new TextEncoder).encode(data);if(dataBuffer.length>segmentLength){const segments=[];for(let i=0;iacc+segment.length,0);let encryptedData=new Uint8Array(totalLength);let offset=0;for(const segment of encryptedSegments){encryptedData.set(segment,offset);offset+=segment.length}return encryptedData.slice(0,offset)}return crypto.subtle.encrypt({name:"RSA-PKCS1-v1_5"},publicKey,dataBuffer)},decryptMergedData:function(privateKey,mergedData){const segmentLength=privateKey.algorithm.modulusLength+7>>3;if(mergedData.length>segmentLength){const segments=[];for(let i=0;i{new_m3u8_body.push(it)})}}new_m3u8_body=new_m3u8_body.join("\n").trim();m3u8_text=[m3u8_start,new_m3u8_body,m3u8_end].join("\n").trim();return m3u8_text}function fixAdM3u8Ai(m3u8_url,headers){let ts=(new Date).getTime();let option=headers?{headers:headers}:{};function b(s1,s2){let i=0;while(iit.startsWith("#")?it:urljoin(m3u8_url,it)).join("\n");m3u8=m3u8.replace(/\n\n/gi,"\n");let last_url=m3u8.split("\n").slice(-1)[0];if(last_url.length<5){last_url=m3u8.split("\n").slice(-2)[0]}if(last_url.includes(".m3u8")&&last_url!==m3u8_url){m3u8_url=urljoin2(m3u8_url,last_url);log("嵌套的m3u8_url:"+m3u8_url);m3u8=request(m3u8_url,option)}let s=m3u8.trim().split("\n").filter(it=>it.trim()).join("\n");let ss=s.split("\n");if(m3u8_url.indexOf("ffzy")>0){let j=0,k1=0,m=0,n=0,t=0;let s2="";for(let i=0;i0){if(maxl>b(firststr,s)+1){if(secondstr.length<5)secondstr=s;kkk2++}else{maxl=b(firststr,s);kkk1++}}kk++;if(kk>=30)break}}if(kkk2>kkk1)firststr=secondstr;let firststrlen=firststr.length;let ml=Math.round(ss.length/2).toString().length;let maxc=0;let laststr=ss.toReversed().find(x=>{if(!x.startsWith("#")){let k=b(reverseString(firststr),reverseString(x));maxl=b(firststr,x);maxc++;if(firststrlen-maxl<=ml+k||maxc>10){return true}}return false});log("最后一条切片:"+laststr);let ad_urls=[];for(let i=0;i=end){return lists}let first=lists[start];let second=lists[end];if(key){try{first=first[key];second=second[key]}catch(e){}}if(option&&typeof option==="function"){try{first=option(first);second=option(second)}catch(e){}}first+="";second+="";if(first.match(/(\d+)/)&&second.match(/(\d+)/)){let num1=Number(first.match(/(\d+)/)[1]);let num2=Number(second.match(/(\d+)/)[1]);if(num1>num2){lists.reverse()}}return lists}let VODS=[];let VOD={};let TABS=[];let LISTS=[];function getQuery(url){try{if(url.indexOf("?")>-1){url=url.slice(url.indexOf("?")+1)}let arr=url.split("#")[0].split("&");const resObj={};arr.forEach(item=>{let arr1=item.split("=");let key=arr1[0];let value=arr1.slice(1).join("=");resObj[key]=value});return resObj}catch(err){log(`getQuery发生错误:${e.message}`);return{}}}function urljoin(fromPath,nowPath){fromPath=fromPath||"";nowPath=nowPath||"";return joinUrl(fromPath,nowPath)}var urljoin2=urljoin;const defaultParser={pdfh:pdfh,pdfa:pdfa,pd:pd};function pdfh2(html,parse){let html2=html;try{if(typeof html!=="string"){html2=html.rr(html.ele).toString()}}catch(e){print(`html对象转文本发生了错误:${e.message}`)}let result=defaultParser.pdfh(html2,parse);let option=parse.includes("&&")?parse.split("&&").slice(-1)[0]:parse.split(" ").slice(-1)[0];if(/style/.test(option.toLowerCase())&&/url\(/.test(result)){try{result=result.match(/url\((.*?)\)/)[1];result=result.replace(/^['|"](.*)['|"]$/,"$1")}catch(e){}}return result}function pdfa2(html,parse){let html2=html;try{if(typeof html!=="string"){html2=html.rr(html.ele).toString()}}catch(e){print(`html对象转文本发生了错误:${e.message}`)}return defaultParser.pdfa(html2,parse)}function pd2(html,parse,uri){let ret=pdfh2(html,parse);if(typeof uri==="undefined"||!uri){uri=""}if(DOM_CHECK_ATTR.test(parse)&&!SPECIAL_URL.test(ret)){if(/http/.test(ret)){ret=ret.slice(ret.indexOf("http"))}else{ret=urljoin(MY_URL,ret)}}return ret}const parseTags={jsp:{pdfh:pdfh2,pdfa:pdfa2,pd:pd2},json:{pdfh(html,parse){if(!parse||!parse.trim()){return""}if(typeof html==="string"){html=JSON.parse(html)}parse=parse.trim();if(!parse.startsWith("$.")){parse="$."+parse}parse=parse.split("||");for(let ps of parse){let ret=cheerio.jp(ps,html);if(Array.isArray(ret)){ret=ret[0]||""}else{ret=ret||""}if(ret&&typeof ret!=="string"){ret=ret.toString()}if(ret){return ret}}return""},pdfa(html,parse){if(!parse||!parse.trim()){return""}if(typeof html==="string"){html=JSON.parse(html)}parse=parse.trim();if(!parse.startsWith("$.")){parse="$."+parse}let ret=cheerio.jp(parse,html);if(Array.isArray(ret)&&Array.isArray(ret[0])&&ret.length===1){return ret[0]||[]}return ret||[]},pd(html,parse){let ret=parseTags.json.pdfh(html,parse);if(ret){return urljoin(MY_URL,ret)}return ret}},jq:{pdfh(html,parse){if(!html||!parse||!parse.trim()){return""}parse=parse.trim();let result=defaultParser.pdfh(html,parse);return result},pdfa(html,parse){if(!html||!parse||!parse.trim()){return[]}parse=parse.trim();let result=defaultParser.pdfa(html,parse);print(`pdfa解析${parse}=>${result.length}`);return result},pd(html,parse,base_url){if(!html||!parse||!parse.trim()){return""}parse=parse.trim();base_url=base_url||MY_URL;return defaultParser.pd(html,parse,base_url)}},getParse(p0){if(p0.startsWith("jsp:")){return this.jsp}else if(p0.startsWith("json:")){return this.json}else if(p0.startsWith("jq:")){return this.jq}else{return this.jq}}};const stringify=JSON.stringify;const jsp=parseTags.jsp;const jq=parseTags.jq;function readFile(filePath){filePath=filePath||"./uri.min.js";var fd=os.open(filePath);var buffer=new ArrayBuffer(1024);var len=os.read(fd,buffer,0,1024);console.log(len);let text=String.fromCharCode.apply(null,new Uint8Array(buffer));console.log(text);return text}function dealJson(html){try{html=html.trim();if(!(html.startsWith("{")&&html.endsWith("}")||html.startsWith("[")&&html.endsWith("]"))){html="{"+html.match(/.*?\{(.*)\}/m)[1]+"}"}}catch(e){}try{html=JSON.parse(html)}catch(e){}return html}var OcrApi={api:OCR_API,classification:function(img){let code="";try{log("通过drpy_ocr验证码接口过验证...");let html="";if(this.api.endsWith("drpy/text")){html=request(this.api,{data:{img:img},headers:{"User-Agent":PC_UA},method:"POST"},true)}else{html=post(this.api,{body:img})}code=html||""}catch(e){log(`OCR识别验证码发生错误:${e.message}`)}return code}};function verifyCode(url){let cnt=0;let host=getHome(url);let cookie="";while(cntit.toLowerCase()==="set-cookie");cookie=setCk?json[setCk].split(";")[0]:""}console.log("cookie:"+cookie);let img=json.body;let code=OcrApi.classification(img);console.log(`第${cnt+1}次验证码识别结果:${code}`);let submit_url=`${host}/index.php/ajax/verify_check?type=search&verify=${code}`;console.log(submit_url);let html=request(submit_url,{headers:{Cookie:cookie},method:"POST"});html=JSON.parse(html);if(html.msg==="ok"){console.log(`第${cnt+1}次验证码提交成功`);return cookie}else if(html.msg!=="ok"&&cnt+1>=OCR_RETRY){cookie=""}}catch(e){console.log(`第${cnt+1}次验证码提交失败:${e.message}`);if(cnt+1>=OCR_RETRY){cookie=""}}cnt+=1}return cookie}function setItem(k,v){local.set(RKEY,k,v);console.log(`规则${RKEY}设置${k} => ${v}`)}function getItem(k,v){return local.get(RKEY,k)||v}function clearItem(k){local.delete(RKEY,k)}function getHome(url){if(!url){return""}let tmp=url.split("//");url=tmp[0]+"//"+tmp[1].split("/")[0];try{url=decodeURIComponent(url)}catch(e){}return url}function buildUrl(url,obj){obj=obj||{};if(url.indexOf("?")<0){url+="?"}let param_list=[];let keys=Object.keys(obj);keys.forEach(it=>{param_list.push(it+"="+obj[it])});let prs=param_list.join("&");if(keys.length>0&&!url.endsWith("?")){url+="&"}url+=prs;return url}function $require(url){eval(request(url))}function keysToLowerCase(obj){return Object.keys(obj).reduce((result,key)=>{const newKey=key.toLowerCase();result[newKey]=obj[key];return result},{})}function buildQueryString(params){const queryArray=[];for(const key in params){if(params.hasOwnProperty(key)){let value=params[key];if(value===undefined||value===null){value=""}else{value=value.toString()}const encodedKey=encodeURIComponent(key);const encodedValue=encodeURIComponent(value);queryArray.push(encodedKey+"="+encodedValue)}}return queryArray.join("&")}function parseQueryString(query){const params={};query.split("&").forEach(function(part){const regex=/^(.*?)=(.*)/;const match=part.match(regex);if(match){const key=decodeURIComponent(match[1]);const value=decodeURIComponent(match[2]);params[key]=value}});return params}function encodeIfContainsSpecialChars(value){const specialChars=":/?#[]@!$'()*+,;=%";if(specialChars.split("").some(char=>value.includes(char))){return encodeURIComponent(value)}return value}function objectToQueryString(obj){const encoded=[];for(let key in obj){if(obj.hasOwnProperty(key)){encoded.push(encodeURIComponent(key)+"="+encodeIfContainsSpecialChars(obj[key]))}}return encoded.join("&")}function request(url,obj,ocr_flag){ocr_flag=ocr_flag||false;if(typeof obj==="undefined"||!obj||obj==={}){if(!fetch_params||!fetch_params.headers){let headers={"User-Agent":MOBILE_UA};if(rule.headers){Object.assign(headers,rule.headers)}if(!fetch_params){fetch_params={}}fetch_params.headers=headers}if(!fetch_params.headers.Referer){fetch_params.headers.Referer=getHome(url)}obj=fetch_params}else{let headers=obj.headers||{};let keys=Object.keys(headers).map(it=>it.toLowerCase());if(!keys.includes("user-agent")){headers["User-Agent"]=MOBILE_UA;if(typeof fetch_params==="object"&&fetch_params&&fetch_params.headers){let fetch_headers=keysToLowerCase(fetch_params.headers);if(fetch_headers["user-agent"]){headers["User-Agent"]=fetch_headers["user-agent"]}}}if(!keys.includes("referer")){headers["Referer"]=getHome(url)}obj.headers=headers}if(rule.encoding&&rule.encoding!=="utf-8"&&!ocr_flag){if(!obj.headers.hasOwnProperty("Content-Type")&&!obj.headers.hasOwnProperty("content-type")){obj.headers["Content-Type"]="text/html; charset="+rule.encoding}}if(typeof obj.body!="undefined"&&obj.body&&typeof obj.body==="string"){if(!obj.headers.hasOwnProperty("Content-Type")&&!obj.headers.hasOwnProperty("content-type")){obj.headers["Content-Type"]="application/x-www-form-urlencoded; charset="+rule.encoding}}else if(typeof obj.body!="undefined"&&obj.body&&typeof obj.body==="object"){obj.data=obj.body;delete obj.body}if(!url){return obj.withHeaders?"{}":""}if(obj.toBase64){obj.buffer=2;delete obj.toBase64}if(obj.redirect===false){obj.redirect=0}if(obj.headers.hasOwnProperty("Content-Type")||obj.headers.hasOwnProperty("content-type")){let _contentType=obj.headers["Content-Type"]||obj.headers["content-type"]||"";if(_contentType.includes("application/x-www-form-urlencoded")){log("custom body is application/x-www-form-urlencoded");if(typeof obj.body=="string"){let temp_obj=parseQueryString(obj.body);console.log(JSON.stringify(temp_obj))}}}console.log(JSON.stringify(obj.headers));console.log("request:"+url+`|method:${obj.method||"GET"}|body:${obj.body||""}`);let res=req(url,obj);let html=res.content||"";if(obj.withHeaders){let htmlWithHeaders=res.headers;htmlWithHeaders.body=html;return JSON.stringify(htmlWithHeaders)}else{return html}}function post(url,obj){obj=obj||{};obj.method="POST";return request(url,obj)}function reqCookie(url,obj,all_cookie){obj=obj||{};obj.withHeaders=true;all_cookie=all_cookie||false;let html=request(url,obj);let json=JSON.parse(html);let setCk=Object.keys(json).find(it=>it.toLowerCase()==="set-cookie");let cookie=setCk?json[setCk]:"";if(Array.isArray(cookie)){cookie=cookie.join(";")}if(!all_cookie){cookie=cookie.split(";")[0]}html=json.body;return{cookie:cookie,html:html}}fetch=request;print=function(data){data=data||"";if(typeof data=="object"&&Object.keys(data).length>0){try{data=JSON.stringify(data);console.log(data)}catch(e){console.log(typeof data+":"+data.length);return}}else if(typeof data=="object"&&Object.keys(data).length<1){console.log("null object")}else{console.log(data)}};log=print;function checkHtml(html,url,obj){if(/\?btwaf=/.test(html)){let btwaf=html.match(/btwaf(.*?)"/)[1];url=url.split("#")[0]+"?btwaf"+btwaf;print("宝塔验证访问链接:"+url);html=request(url,obj)}return html}function getCode(url,obj){let html=request(url,obj);html=checkHtml(html,url,obj);return html}function getHtml(url){let obj={};if(rule.headers){obj.headers=rule.headers}let cookie=getItem(RULE_CK,"");if(cookie){if(obj.headers&&!Object.keys(obj.headers).map(it=>it.toLowerCase()).includes("cookie")){log("历史无cookie,新增过验证后的cookie");obj.headers["Cookie"]=cookie}else if(obj.headers&&obj.headers.cookie&&obj.headers.cookie!==cookie){obj.headers["Cookie"]=cookie;log("历史有小写过期的cookie,更新过验证后的cookie")}else if(obj.headers&&obj.headers.Cookie&&obj.headers.Cookie!==cookie){obj.headers["Cookie"]=cookie;log("历史有大写过期的cookie,更新过验证后的cookie")}else if(!obj.headers){obj.headers={Cookie:cookie};log("历史无headers,更新过验证后的含cookie的headers")}}let html=getCode(url,obj);return html}function homeParse(homeObj){fetch_params=JSON.parse(JSON.stringify(rule_fetch_params));let classes=[];if(homeObj.class_name&&homeObj.class_url){let names=homeObj.class_name.split("&");let urls=homeObj.class_url.split("&");let cnt=Math.min(names.length,urls.length);for(let i=0;i0){classes=list}}}catch(e){console.log(e.message)}}else if(p.length>=3&&!is_json){try{let html=homeObj.home_html||getHtml(homeObj.MY_URL);if(html){homeHtmlCache=html;let list=_pdfa(html,p0);if(list&&list.length>0){list.forEach((it,idex)=>{try{let name=_pdfh(it,p[1]);if(homeObj.cate_exclude&&new RegExp(homeObj.cate_exclude).test(name)){return}let url=_pd(it,p[2]);if(p.length>3&&p[3]&&!homeObj.home_html){let exp=new RegExp(p[3]);url=url.match(exp)[1]}classes.push({type_id:url.trim(),type_name:name.trim()})}catch(e){console.log(`分类列表定位第${idex}个元素正常报错:${e.message}`)}})}}}catch(e){console.log(e.message)}}}}classes=classes.filter(it=>!homeObj.cate_exclude||!new RegExp(homeObj.cate_exclude).test(it.type_name));let resp={class:classes};if(homeObj.filter){resp.filters=homeObj.filter}console.log(JSON.stringify(resp));return JSON.stringify(resp)}function getPP(p,pn,pp,ppn){try{let ps=p[pn]==="*"&&pp.length>ppn?pp[ppn]:p[pn];return ps}catch(e){return""}}function homeVodParse(homeVodObj){fetch_params=JSON.parse(JSON.stringify(rule_fetch_params));let d=[];MY_URL=homeVodObj.homeUrl;console.log(MY_URL);let t1=(new Date).getTime();let p=homeVodObj.推荐;print("p:"+p);if(p==="*"&&rule.一级){p=rule.一级;homeVodObj.double=false}if(!p||typeof p!=="string"){return"{}"}p=p.trim();let pp=rule.一级?rule.一级.split(";"):[];if(p.startsWith("js:")){const TYPE="home";var input=MY_URL;HOST=rule.host;eval(p.replace("js:",""));d=VODS}else{p=p.split(";");if(!homeVodObj.double&&p.length<5){return"{}"}else if(homeVodObj.double&&p.length<6){return"{}"}let p0=getPP(p,0,pp,0);let _ps=parseTags.getParse(p0);_pdfa=_ps.pdfa;_pdfh=_ps.pdfh;_pd=_ps.pd;let is_json=p0.startsWith("json:");p0=p0.replace(/^(jsp:|json:|jq:)/,"");let html=homeHtmlCache||getHtml(MY_URL);homeHtmlCache=undefined;if(is_json){html=dealJson(html)}try{console.log("double:"+homeVodObj.double);if(homeVodObj.double){let items=_pdfa(html,p0);let p1=getPP(p,1,pp,0);let p2=getPP(p,2,pp,1);let p3=getPP(p,3,pp,2);let p4=getPP(p,4,pp,3);let p5=getPP(p,5,pp,4);let p6=getPP(p,6,pp,5);for(let item of items){let items2=_pdfa(item,p1);for(let item2 of items2){try{let title=_pdfh(item2,p2);let img="";try{img=_pd(item2,p3)}catch(e){}let desc="";try{desc=_pdfh(item2,p4)}catch(e){}let links=[];for(let _p5 of p5.split("+")){let link=!homeVodObj.detailUrl?_pd(item2,_p5,MY_URL):_pdfh(item2,_p5);links.push(link)}let content;if(p.length>6&&p[6]){content=_pdfh(item2,p6)}else{content=""}let vid=links.join("$");if(rule.二级==="*"){vid=vid+"@@"+title+"@@"+img}let vod={vod_name:title,vod_pic:img,vod_remarks:desc,vod_content:content,vod_id:vid};d.push(vod)}catch(e){console.log(`首页列表双层定位处理发生错误:${e.message}`)}}}}else{let items=_pdfa(html,p0);let p1=getPP(p,1,pp,1);let p2=getPP(p,2,pp,2);let p3=getPP(p,3,pp,3);let p4=getPP(p,4,pp,4);let p5=getPP(p,5,pp,5);for(let item of items){try{let title=_pdfh(item,p1);let img="";try{img=_pd(item,p2,MY_URL)}catch(e){}let desc="";try{desc=_pdfh(item,p3)}catch(e){}let links=[];for(let _p5 of p4.split("+")){let link=!homeVodObj.detailUrl?_pd(item,_p5,MY_URL):_pdfh(item,_p5);links.push(link)}let content;if(p.length>5&&p[5]){content=_pdfh(item,p5)}else{content=""}let vid=links.join("$");if(rule.二级==="*"){vid=vid+"@@"+title+"@@"+img}let vod={vod_name:title,vod_pic:img,vod_remarks:desc,vod_content:content,vod_id:vid};d.push(vod)}catch(e){console.log(`首页列表单层定位处理发生错误:${e.message}`)}}}}catch(e){}}let t2=(new Date).getTime();console.log("加载首页推荐耗时:"+(t2-t1)+"毫秒");if(rule.图片替换){if(rule.图片替换.startsWith("js:")){d.forEach(it=>{try{var input=it.vod_pic;eval(rule.图片替换.trim().replace("js:",""));it.vod_pic=input}catch(e){log(`图片:${it.vod_pic}替换错误:${e.message}`)}})}else if(rule.图片替换.includes("=>")){let replace_from=rule.图片替换.split("=>")[0];let replace_to=rule.图片替换.split("=>")[1];d.forEach(it=>{if(it.vod_pic&&it.vod_pic.startsWith("http")){it.vod_pic=it.vod_pic.replace(replace_from,replace_to)}})}}if(rule.图片来源){d.forEach(it=>{if(it.vod_pic&&it.vod_pic.startsWith("http")){it.vod_pic=it.vod_pic+rule.图片来源}})}if(d.length>0){print(d.slice(0,2))}return JSON.stringify({list:d})}function categoryParse(cateObj){fetch_params=JSON.parse(JSON.stringify(rule_fetch_params));let p=cateObj.一级;if(!p||typeof p!=="string"){return"{}"}let d=[];let url=cateObj.url.replaceAll("fyclass",cateObj.tid);if(cateObj.pg===1&&url.includes("[")&&url.includes("]")){url=url.split("[")[1].split("]")[0]}else if(cateObj.pg>1&&url.includes("[")&&url.includes("]")){url=url.split("[")[0]}if(rule.filter_url){if(!/fyfilter/.test(url)){if(!url.endsWith("&")&&!rule.filter_url.startsWith("&")){url+="&"}url+=rule.filter_url}else{url=url.replace("fyfilter",rule.filter_url)}url=url.replaceAll("fyclass",cateObj.tid);let fl=cateObj.filter?cateObj.extend:{};if(rule.filter_def&&typeof rule.filter_def==="object"){try{if(Object.keys(rule.filter_def).length>0&&rule.filter_def.hasOwnProperty(cateObj.tid)){let self_fl_def=rule.filter_def[cateObj.tid];if(self_fl_def&&typeof self_fl_def==="object"){let fl_def=JSON.parse(JSON.stringify(self_fl_def));fl=Object.assign(fl_def,fl)}}}catch(e){print(`合并不同分类对应的默认筛选出错:${e.message}`)}}let new_url;new_url=cheerio.jinja2(url,{fl:fl,fyclass:cateObj.tid});url=new_url}if(/fypage/.test(url)){if(url.includes("(")&&url.includes(")")){let url_rep=url.match(/.*?\((.*)\)/)[1];let cnt_page=url_rep.replaceAll("fypage",cateObj.pg);let cnt_pg=eval(cnt_page);url=url.replaceAll(url_rep,cnt_pg).replaceAll("(","").replaceAll(")","")}else{url=url.replaceAll("fypage",cateObj.pg)}}MY_URL=url;console.log(MY_URL);p=p.trim();const MY_CATE=cateObj.tid;if(p.startsWith("js:")){var MY_FL=cateObj.extend;const TYPE="cate";var input=MY_URL;const MY_PAGE=cateObj.pg;var desc="";eval(p.trim().replace("js:",""));d=VODS}else{p=p.split(";");if(p.length<5){return"{}"}let _ps=parseTags.getParse(p[0]);_pdfa=_ps.pdfa;_pdfh=_ps.pdfh;_pd=_ps.pd;let is_json=p[0].startsWith("json:");p[0]=p[0].replace(/^(jsp:|json:|jq:)/,"");try{let html=getHtml(MY_URL);if(html){if(is_json){html=dealJson(html)}let list=_pdfa(html,p[0]);list.forEach(it=>{let links=p[4].split("+").map(p4=>{return!rule.detailUrl?_pd(it,p4,MY_URL):_pdfh(it,p4)});let link=links.join("$");let vod_id=rule.detailUrl?MY_CATE+"$"+link:link;let vod_name=_pdfh(it,p[1]).replace(/\n|\t/g,"").trim();let vod_pic=_pd(it,p[2],MY_URL);if(rule.二级==="*"){vod_id=vod_id+"@@"+vod_name+"@@"+vod_pic}d.push({vod_id:vod_id,vod_name:vod_name,vod_pic:vod_pic,vod_remarks:_pdfh(it,p[3]).replace(/\n|\t/g,"").trim()})})}}catch(e){console.log(e.message)}}if(rule.图片替换){if(rule.图片替换.startsWith("js:")){d.forEach(it=>{try{var input=it.vod_pic;eval(rule.图片替换.trim().replace("js:",""));it.vod_pic=input}catch(e){log(`图片:${it.vod_pic}替换错误:${e.message}`)}})}else if(rule.图片替换.includes("=>")){let replace_from=rule.图片替换.split("=>")[0];let replace_to=rule.图片替换.split("=>")[1];d.forEach(it=>{if(it.vod_pic&&it.vod_pic.startsWith("http")){it.vod_pic=it.vod_pic.replace(replace_from,replace_to)}})}}if(rule.图片来源){d.forEach(it=>{if(it.vod_pic&&it.vod_pic.startsWith("http")){it.vod_pic=it.vod_pic+rule.图片来源}})}if(d.length>0){print(d.slice(0,2))}let pagecount=0;if(rule.pagecount&&typeof rule.pagecount==="object"&&rule.pagecount.hasOwnProperty(MY_CATE)){print(`MY_CATE:${MY_CATE},pagecount:${JSON.stringify(rule.pagecount)}`);pagecount=parseInt(rule.pagecount[MY_CATE])}let nodata={list:[{vod_name:"无数据,防无限请求",vod_id:"no_data",vod_remarks:"不要点,会崩的",vod_pic:"https://ghproxy.net/https://raw.githubusercontent.com/hjdhnx/dr_py/main/404.jpg"}],total:1,pagecount:1,page:1,limit:1};let vod=d.length<1?JSON.stringify(nodata):JSON.stringify({page:parseInt(cateObj.pg),pagecount:pagecount||999,limit:20,total:999,list:d});return vod}function searchParse(searchObj){fetch_params=JSON.parse(JSON.stringify(rule_fetch_params));let d=[];if(!searchObj.searchUrl){return"{}"}if(rule.searchNoPage&&Number(searchObj.pg)>1){return"{}"}let p=searchObj.搜索==="*"&&rule.一级?rule.一级:searchObj.搜索;if(!p||typeof p!=="string"){return"{}"}p=p.trim();let pp=rule.一级?rule.一级.split(";"):[];let url=searchObj.searchUrl.replaceAll("**",searchObj.wd);if(searchObj.pg===1&&url.includes("[")&&url.includes("]")&&!url.includes("#")){url=url.split("[")[1].split("]")[0]}else if(searchObj.pg>1&&url.includes("[")&&url.includes("]")&&!url.includes("#")){url=url.split("[")[0]}if(/fypage/.test(url)){if(url.includes("(")&&url.includes(")")){let url_rep=url.match(/.*?\((.*)\)/)[1];let cnt_page=url_rep.replaceAll("fypage",searchObj.pg);let cnt_pg=eval(cnt_page);url=url.replaceAll(url_rep,cnt_pg).replaceAll("(","").replaceAll(")","")}else{url=url.replaceAll("fypage",searchObj.pg)}}MY_URL=url;console.log(MY_URL);if(p.startsWith("js:")){const TYPE="search";const MY_PAGE=searchObj.pg;const KEY=searchObj.wd;var input=MY_URL;var detailUrl=rule.detailUrl||"";eval(p.trim().replace("js:",""));d=VODS}else{p=p.split(";");if(p.length<5){return"{}"}let p0=getPP(p,0,pp,0);let _ps=parseTags.getParse(p0);_pdfa=_ps.pdfa;_pdfh=_ps.pdfh;_pd=_ps.pd;let is_json=p0.startsWith("json:");p0=p0.replace(/^(jsp:|json:|jq:)/,"");try{let req_method=MY_URL.split(";").length>1?MY_URL.split(";")[1].toLowerCase():"get";let html;if(req_method==="post"){let rurls=MY_URL.split(";")[0].split("#");let rurl=rurls[0];let params=rurls.length>1?rurls[1]:"";print(`post=》rurl:${rurl},params:${params}`);let _fetch_params=JSON.parse(JSON.stringify(rule_fetch_params));let postData={body:params};Object.assign(_fetch_params,postData);html=post(rurl,_fetch_params)}else if(req_method==="postjson"){let rurls=MY_URL.split(";")[0].split("#");let rurl=rurls[0];let params=rurls.length>1?rurls[1]:"";print(`postjson-》rurl:${rurl},params:${params}`);try{params=JSON.parse(params)}catch(e){params="{}"}let _fetch_params=JSON.parse(JSON.stringify(rule_fetch_params));let postData={body:params};Object.assign(_fetch_params,postData);html=post(rurl,_fetch_params)}else{html=getHtml(MY_URL)}if(html){let search_tag=rule.搜索验证标识||"系统安全验证|输入验证码";if(new RegExp(search_tag).test(html)){let cookie=verifyCode(MY_URL);if(cookie){console.log(`本次成功过验证,cookie:${cookie}`);setItem(RULE_CK,cookie)}else{console.log(`本次自动过搜索验证失败,cookie:${cookie}`)}html=getHtml(MY_URL)}if(!html.includes(searchObj.wd)){console.log("搜索结果源码未包含关键字,疑似搜索失败,正为您打印结果源码");console.log(html)}if(is_json){html=dealJson(html)}let list=_pdfa(html,p0);let p1=getPP(p,1,pp,1);let p2=getPP(p,2,pp,2);let p3=getPP(p,3,pp,3);let p4=getPP(p,4,pp,4);let p5=getPP(p,5,pp,5);list.forEach(it=>{let links=p4.split("+").map(_p4=>{return!rule.detailUrl?_pd(it,_p4,MY_URL):_pdfh(it,_p4)});let link=links.join("$");let content;if(p.length>5&&p[5]){content=_pdfh(it,p5)}else{content=""}let vod_id=link;let vod_name=_pdfh(it,p1).replace(/\n|\t/g,"").trim();let vod_pic=_pd(it,p2,MY_URL);if(rule.二级==="*"){vod_id=vod_id+"@@"+vod_name+"@@"+vod_pic}let ob={vod_id:vod_id,vod_name:vod_name,vod_pic:vod_pic,vod_remarks:_pdfh(it,p3).replace(/\n|\t/g,"").trim(),vod_content:content.replace(/\n|\t/g,"").trim()};d.push(ob)})}}catch(e){print(`搜索发生错误:${e.message}`);return"{}"}}if(rule.图片替换){if(rule.图片替换.startsWith("js:")){d.forEach(it=>{try{var input=it.vod_pic;eval(rule.图片替换.trim().replace("js:",""));it.vod_pic=input}catch(e){log(`图片:${it.vod_pic}替换错误:${e.message}`)}})}else if(rule.图片替换.includes("=>")){let replace_from=rule.图片替换.split("=>")[0];let replace_to=rule.图片替换.split("=>")[1];d.forEach(it=>{if(it.vod_pic&&it.vod_pic.startsWith("http")){it.vod_pic=it.vod_pic.replace(replace_from,replace_to)}})}}if(rule.图片来源){d.forEach(it=>{if(it.vod_pic&&it.vod_pic.startsWith("http")){it.vod_pic=it.vod_pic+rule.图片来源}})}return JSON.stringify({page:parseInt(searchObj.pg),pagecount:10,limit:20,total:100,list:d})}function detailParse(detailObj){let t1=(new Date).getTime();fetch_params=JSON.parse(JSON.stringify(rule_fetch_params));let orId=detailObj.orId;let vod_name="片名";let vod_pic="";let vod_id=orId;if(rule.二级==="*"){let extra=orId.split("@@");vod_name=extra.length>1?extra[1]:vod_name;vod_pic=extra.length>2?extra[2]:vod_pic}let vod={vod_id:vod_id,vod_name:vod_name,vod_pic:vod_pic,type_name:"类型",vod_year:"年份",vod_area:"地区",vod_remarks:"更新信息",vod_actor:"主演",vod_director:"导演",vod_content:"简介"};let p=detailObj.二级;let url=detailObj.url;let detailUrl=detailObj.detailUrl;let fyclass=detailObj.fyclass;let tab_exclude=detailObj.tab_exclude;let html=detailObj.html||"";MY_URL=url;if(detailObj.二级访问前){try{print(`尝试在二级访问前执行代码:${detailObj.二级访问前}`);eval(detailObj.二级访问前.trim().replace("js:",""))}catch(e){print(`二级访问前执行代码出现错误:${e.message}`)}}if(p==="*"){vod.vod_play_from="道长在线";vod.vod_remarks=detailUrl;vod.vod_actor="没有二级,只有一级链接直接嗅探播放";vod.vod_content=MY_URL;vod.vod_play_url="嗅探播放$"+MY_URL.split("@@")[0]}else if(typeof p==="string"&&p.trim().startsWith("js:")){const TYPE="detail";var input=MY_URL;var play_url="";eval(p.trim().replace("js:",""));vod=VOD;console.log(JSON.stringify(vod))}else if(p&&typeof p==="object"){let tt1=(new Date).getTime();if(!html){html=getHtml(MY_URL)}print(`二级${MY_URL}仅获取源码耗时:${(new Date).getTime()-tt1}毫秒`);let _ps;if(p.is_json){print("二级是json");_ps=parseTags.json;html=dealJson(html)}else if(p.is_jsp){print("二级是jsp");_ps=parseTags.jsp}else if(p.is_jq){print("二级是jq");_ps=parseTags.jq}else{print("二级默认jq");_ps=parseTags.jq}let tt2=(new Date).getTime();print(`二级${MY_URL}获取并装载源码耗时:${tt2-tt1}毫秒`);_pdfa=_ps.pdfa;_pdfh=_ps.pdfh;_pd=_ps.pd;if(p.title){let p1=p.title.split(";");vod.vod_name=_pdfh(html,p1[0]).replace(/\n|\t/g,"").trim();let type_name=p1.length>1?_pdfh(html,p1[1]).replace(/\n|\t/g,"").replace(/ /g,"").trim():"";vod.type_name=type_name||vod.type_name}if(p.desc){try{let p1=p.desc.split(";");vod.vod_remarks=_pdfh(html,p1[0]).replace(/\n|\t/g,"").trim();vod.vod_year=p1.length>1?_pdfh(html,p1[1]).replace(/\n|\t/g,"").trim():"";vod.vod_area=p1.length>2?_pdfh(html,p1[2]).replace(/\n|\t/g,"").trim():"";vod.vod_actor=p1.length>3?_pdfh(html,p1[3]).replace(/\n|\t/g,"").trim():"";vod.vod_director=p1.length>4?_pdfh(html,p1[4]).replace(/\n|\t/g,"").trim():""}catch(e){}}if(p.content){try{let p1=p.content.split(";");vod.vod_content=_pdfh(html,p1[0]).replace(/\n|\t/g,"").trim()}catch(e){}}if(p.img){try{let p1=p.img.split(";");vod.vod_pic=_pd(html,p1[0],MY_URL)}catch(e){}}let vod_play_from="$$$";let playFrom=[];if(p.重定向&&p.重定向.startsWith("js:")){print("开始执行重定向代码:"+p.重定向);html=eval(p.重定向.replace("js:",""))}if(p.tabs){if(p.tabs.startsWith("js:")){print("开始执行tabs代码:"+p.tabs);var input=MY_URL;eval(p.tabs.replace("js:",""));playFrom=TABS}else{let p_tab=p.tabs.split(";")[0];let vHeader=_pdfa(html,p_tab);console.log(vHeader.length);let tab_text=p.tab_text||"body&&Text";let new_map={};for(let v of vHeader){let v_title=_pdfh(v,tab_text).trim();if(!v_title){v_title="线路空"}console.log(v_title);if(tab_exclude&&new RegExp(tab_exclude).test(v_title)){continue}if(!new_map.hasOwnProperty(v_title)){new_map[v_title]=1}else{new_map[v_title]+=1}if(new_map[v_title]>1){v_title+=Number(new_map[v_title]-1)}playFrom.push(v_title)}}console.log(JSON.stringify(playFrom))}else{playFrom=["道长在线"]}vod.vod_play_from=playFrom.join(vod_play_from);let vod_play_url="$$$";let vod_tab_list=[];if(p.lists){if(p.lists.startsWith("js:")){print("开始执行lists代码:"+p.lists);try{var input=MY_URL;var play_url="";eval(p.lists.replace("js:",""));for(let i in LISTS){if(LISTS.hasOwnProperty(i)){try{LISTS[i]=LISTS[i].map(it=>it.split("$").slice(0,2).join("$"))}catch(e){print(`格式化LISTS发生错误:${e.message}`)}}}vod_play_url=LISTS.map(it=>it.join("#")).join(vod_play_url)}catch(e){print(`js执行lists: 发生错误:${e.message}`)}}else{let list_text=p.list_text||"body&&Text";let list_url=p.list_url||"a&&href";let list_url_prefix=p.list_url_prefix||"";let is_tab_js=p.tabs.trim().startsWith("js:");for(let i=0;i1&&!is_tab_js?p.tabs.split(";")[1]:"";let p1=p.lists.replaceAll("#idv",tab_name).replaceAll("#id",i);tab_ext=tab_ext.replaceAll("#idv",tab_name).replaceAll("#id",i);let tabName=tab_ext?_pdfh(html,tab_ext):tab_name;console.log(tabName);let new_vod_list=[];let tt1=(new Date).getTime();if(typeof pdfl==="function"){new_vod_list=pdfl(html,p1,list_text,list_url,MY_URL);if(list_url_prefix){new_vod_list=new_vod_list.map(it=>it.split("$")[0]+"$"+list_url_prefix+it.split("$").slice(1).join("$"))}}else{let vodList=[];try{vodList=_pdfa(html,p1);console.log("len(vodList):"+vodList.length)}catch(e){}for(let i=0;i0){new_vod_list=forceOrder(new_vod_list,"",x=>x.split("$")[0]);console.log(`drpy影响性能代码共计列表数循环次数:${new_vod_list.length},耗时:${(new Date).getTime()-tt1}毫秒`)}let vlist=new_vod_list.join("#");vod_tab_list.push(vlist)}vod_play_url=vod_tab_list.join(vod_play_url)}}vod.vod_play_url=vod_play_url}if(rule.图片替换&&rule.图片替换.includes("=>")){let replace_from=rule.图片替换.split("=>")[0];let replace_to=rule.图片替换.split("=>")[1];vod.vod_pic=vod.vod_pic.replace(replace_from,replace_to)}if(rule.图片来源&&vod.vod_pic&&vod.vod_pic.startsWith("http")){vod.vod_pic=vod.vod_pic+rule.图片来源}if(!vod.vod_id||vod_id.includes("$")&&vod.vod_id!==vod_id){vod.vod_id=vod_id}let t2=(new Date).getTime();console.log(`加载二级界面${MY_URL}耗时:${t2-t1}毫秒`);try{vod=vodDeal(vod)}catch(e){console.log(`vodDeal发生错误:${e.message}`)}return JSON.stringify({list:[vod]})}function get_tab_index(vod){let obj={};vod.vod_play_from.split("$$$").forEach((it,index)=>{obj[it]=index});return obj}function vodDeal(vod){let vod_play_from=vod.vod_play_from.split("$$$");let vod_play_url=vod.vod_play_url.split("$$$");let tab_removed_list=vod_play_from;let tab_ordered_list=vod_play_from;let tab_renamed_list=vod_play_from;let tab_list=vod_play_from;let play_ordered_list=vod_play_url;if(rule.tab_remove&&rule.tab_remove.length>0||rule.tab_order&&rule.tab_order.length>0){let tab_index_dict=get_tab_index(vod);if(rule.tab_remove&&rule.tab_remove.length>0){tab_removed_list=vod_play_from.filter(it=>!rule.tab_remove.includes(it));tab_list=tab_removed_list}if(rule.tab_order&&rule.tab_order.length>0){let tab_order=rule.tab_order;tab_ordered_list=tab_removed_list.sort((a,b)=>{const getOrderIndex=(tabName,orderRules)=>{for(let i=0;ivod_play_url[tab_index_dict[it]])}if(rule.tab_rename&&typeof rule.tab_rename==="object"&Object.keys(rule.tab_rename).length>0){tab_renamed_list=tab_list.map(it=>rule.tab_rename[it]||it);tab_list=tab_renamed_list}vod.vod_play_from=tab_list.join("$$$");vod.vod_play_url=play_ordered_list.join("$$$");return vod}function tellIsJx(url){try{let is_vip=!/\.(m3u8|mp4|m4a)$/.test(url.split("?")[0])&&是否正版(url);return is_vip?1:0}catch(e){return 1}}function playParse(playObj){fetch_params=JSON.parse(JSON.stringify(rule_fetch_params));MY_URL=playObj.url;var MY_FLAG=playObj.flag;if(!/http/.test(MY_URL)){try{MY_URL=base64Decode(MY_URL)}catch(e){}}MY_URL=decodeURIComponent(MY_URL);var input=MY_URL;var flag=MY_FLAG;let common_play={parse:SPECIAL_URL.test(input)||/^(push:)/.test(input)?0:1,url:input,flag:flag,jx:tellIsJx(input)};let lazy_play;if(!rule.play_parse||!rule.lazy){lazy_play=common_play}else if(rule.play_parse&&rule.lazy&&typeof rule.lazy==="string"){try{let lazy_code=rule.lazy.trim();if(lazy_code.startsWith("js:")){lazy_code=lazy_code.replace("js:","").trim()}print("开始执行js免嗅=>"+lazy_code);eval(lazy_code);lazy_play=typeof input==="object"?input:{parse:SPECIAL_URL.test(input)||/^(push:)/.test(input)?0:1,jx:tellIsJx(input),url:input}}catch(e){print(`js免嗅错误:${e.message}`);lazy_play=common_play}}else{lazy_play=common_play}if(Array.isArray(rule.play_json)&&rule.play_json.length>0){let web_url=lazy_play.url;for(let pjson of rule.play_json){if(pjson.re&&(pjson.re==="*"||web_url.match(new RegExp(pjson.re)))){if(pjson.json&&typeof pjson.json==="object"){let base_json=pjson.json;lazy_play=Object.assign(lazy_play,base_json);break}}}}else if(rule.play_json&&!Array.isArray(rule.play_json)){let base_json={jx:1,parse:1};lazy_play=Object.assign(lazy_play,base_json)}else if(!rule.play_json){let base_json={jx:0,parse:1};lazy_play=Object.assign(lazy_play,base_json)}console.log(JSON.stringify(lazy_play));return JSON.stringify(lazy_play)}function proxyParse(proxyObj){var input=proxyObj.params;if(proxyObj.proxy_rule){log("准备执行本地代理规则:\n"+proxyObj.proxy_rule);try{eval(proxyObj.proxy_rule);if(input&&input!==proxyObj.params&&Array.isArray(input)&&input.length>=3){return input}else{return[404,"text/plain","Not Found"]}}catch(e){return[500,"text/plain","代理规则错误:"+e.message]}}else{return[404,"text/plain","Not Found"]}}function isVideoParse(isVideoObj){var input=isVideoObj.url;if(!isVideoObj.t){let re_matcher=new RegExp(isVideoObj.isVideo,"i");return re_matcher.test(input)}else{try{eval(isVideoObj.isVideo);if(typeof input==="boolean"){return input}else{return false}}catch(e){log(`执行嗅探规则发生错误:${e.message}`);return false}}}function removeHeader(content,options={}){const{mode="header-only",fileType}=options;const COMMENT_CONFIG={".js":{start:"/*",end:"*/",regex:/^\s*\/\*([\s\S]*?)\*\/\s*/,headerRegex:/@header\(([\s\S]*?)\)/,topCommentsRegex:/^(\s*(\/\/[^\n]*\n|\/\*[\s\S]*?\*\/)\s*)+/},".py":{start:'"""',end:'"""',regex:/^\s*"""([\s\S]*?)"""\s*/,headerRegex:/@header\(([\s\S]*?)\)/,topCommentsRegex:/^(\s*(#[^\n]*\n|'''[\s\S]*?'''|"""[\s\S]*?""")\s*)+/}};if(!fileType)throw new Error("fileType option is required");const ext=fileType.startsWith(".")?fileType:`.${fileType}`;const config=COMMENT_CONFIG[ext];if(!config)throw new Error(`Unsupported file type: ${ext}`);if(mode==="top-comments"){const match=content.match(config.topCommentsRegex);if(match){return content.substring(match[0].length).trim()}return content.trim()}const match=content.match(config.regex);if(!match)return content.trim();let[fullComment,innerContent]=match;if(config.headerRegex.test(innerContent)){innerContent=innerContent.replace(config.headerRegex,"");const cleanedInner=innerContent.split("\n").filter(line=>line.trim().length>0).join("\n");if(!cleanedInner.trim()){return content.replace(fullComment,"").trim()}else{const newComment=`${config.start}${cleanedInner}${config.end}`;return content.replace(fullComment,newComment).trim()}}return content.trim()}function getOriginalJs(js_code){let current_match=/var rule|function|let |var |const|class Rule|async|this\./;if(current_match.test(js_code)){return js_code}js_code=removeHeader(js_code,{mode:"top-comments",fileType:".js"});let rsa_private_key="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqin/jUpqM6+fgYP/oMqj9zcdHMM0mEZXLeTyixIJWP53lzJV2N2E3OP6BBpUmq2O1a9aLnTIbADBaTulTNiOnVGoNG58umBnupnbmmF8iARbDp2mTzdMMeEgLdrfXS6Y3VvazKYALP8EhEQykQVarexR78vRq7ltY3quXx7cgI0ROfZz5Sw3UOLQJ+VoWmwIxu9AMEZLVzFDQN93hzuzs3tNyHK6xspBGB7zGbwCg+TKi0JeqPDrXxYUpAz1cQ/MO+Da0WgvkXnvrry8NQROHejdLVOAslgr6vYthH9bKbsGyNY3H+P12kcxo9RAcVveONnZbcMyxjtF5dWblaernAgMBAAECggEAGdEHlSEPFmAr5PKqKrtoi6tYDHXdyHKHC5tZy4YV+Pp+a6gxxAiUJejx1hRqBcWSPYeKne35BM9dgn5JofgjI5SKzVsuGL6bxl3ayAOu+xXRHWM9f0t8NHoM5fdd0zC3g88dX3fb01geY2QSVtcxSJpEOpNH3twgZe6naT2pgiq1S4okpkpldJPo5GYWGKMCHSLnKGyhwS76gF8bTPLoay9Jxk70uv6BDUMlA4ICENjmsYtd3oirWwLwYMEJbSFMlyJvB7hjOjR/4RpT4FPnlSsIpuRtkCYXD4jdhxGlvpXREw97UF2wwnEUnfgiZJ2FT/MWmvGGoaV/CfboLsLZuQKBgQDTNZdJrs8dbijynHZuuRwvXvwC03GDpEJO6c1tbZ1s9wjRyOZjBbQFRjDgFeWs9/T1aNBLUrgsQL9c9nzgUziXjr1Nmu52I0Mwxi13Km/q3mT+aQfdgNdu6ojsI5apQQHnN/9yMhF6sNHg63YOpH+b+1bGRCtr1XubuLlumKKscwKBgQDOtQ2lQjMtwsqJmyiyRLiUOChtvQ5XI7B2mhKCGi8kZ+WEAbNQcmThPesVzW+puER6D4Ar4hgsh9gCeuTaOzbRfZ+RLn3Aksu2WJEzfs6UrGvm6DU1INn0z/tPYRAwPX7sxoZZGxqML/z+/yQdf2DREoPdClcDa2Lmf1KpHdB+vQKBgBXFCVHz7a8n4pqXG/HvrIMJdEpKRwH9lUQS/zSPPtGzaLpOzchZFyQQBwuh1imM6Te+VPHeldMh3VeUpGxux39/m+160adlnRBS7O7CdgSsZZZ/dusS06HAFNraFDZf1/VgJTk9BeYygX+AZYu+0tReBKSs9BjKSVJUqPBIVUQXAoGBAJcZ7J6oVMcXxHxwqoAeEhtvLcaCU9BJK36XQ/5M67ceJ72mjJC6/plUbNukMAMNyyi62gO6I9exearecRpB/OGIhjNXm99Ar59dAM9228X8gGfryLFMkWcO/fNZzb6lxXmJ6b2LPY3KqpMwqRLTAU/zy+ax30eFoWdDHYa4X6e1AoGAfa8asVGOJ8GL9dlWufEeFkDEDKO9ww5GdnpN+wqLwePWqeJhWCHad7bge6SnlylJp5aZXl1+YaBTtOskC4Whq9TP2J+dNIgxsaF5EFZQJr8Xv+lY9lu0CruYOh9nTNF9x3nubxJgaSid/7yRPfAGnsJRiknB5bsrCvgsFQFjJVs=";let decode_content="";function aes_decrypt(data){const keyHex="686A64686E780A0A0A0A0A0A0A0A0A0A";const ivHex="647A797964730A0A0A0A0A0A0A0A0A0A";const keyArray=new Uint8Array(Buffer.from(keyHex,"hex"));const ivArray=new Uint8Array(Buffer.from(ivHex,"hex"));const encryptedArray=new Uint8Array(Buffer.from(data,"base64"));const key=crypto.subtle.importKey("raw",keyArray,{name:"AES-CBC"},false,["decrypt"]);try{const decryptedArray=crypto.subtle.decrypt({name:"AES-CBC",iv:ivArray},key,encryptedArray);const decryptedString=(new TextDecoder).decode(decryptedArray);return decryptedString}catch(e){console.error("解密失败:",e);return null}}let error_log=false;function logger(text){if(error_log){log(text)}}let decode_funcs=[text=>{try{return ungzip(text)}catch(e){logger("非gzip加密");return""}},text=>{try{return base64Decode(text)}catch(e){logger("非b64加密");return""}},text=>{try{return aes_decrypt(text)}catch(e){logger("非aes加密");return""}},text=>{try{return RSA.decode(text,rsa_private_key,null)}catch(e){logger("非rsa加密");return""}}];let func_index=0;while(!current_match.test(decode_content)){decode_content=decode_funcs[func_index](js_code);func_index++;if(func_index>=decode_funcs.length){break}}return decode_content}function runMain(main_func_code,arg){let mainFunc=function(){return""};try{eval(main_func_code+"\nmainFunc=main;");return mainFunc(arg)}catch(e){log(`执行main_funct发生了错误:${e.message}`);return""}}function init(ext){console.log("init");rule={};rule_fetch_params={};fetch_params=null;try{let muban=模板.getMubans();if(typeof ext=="object"){rule=ext}else if(typeof ext=="string"){let is_file=ext.startsWith("file://");if(ext.startsWith("http")||is_file){let query=getQuery(ext);if(is_file){ext=ext.split("?")[0]}let js=request(ext,{method:"GET"});if(js){js=getOriginalJs(js);eval("(function(){"+js.replace("var rule","rule")+"})()")}if(query.type==="url"&&query.params){if(is_file&&/^http/.test(query.params)){rule.params=query.params}else{rule.params=urljoin(ext,query.params)}}else if(query.params){rule.params=query.params}}else{ext=getOriginalJs(ext);eval("(function(){"+ext.replace("var rule","rule")+"})()")}}else{console.log(`规则加载失败,不支持的规则类型:${typeof ext}`);return}rule.host=(rule.host||"").rstrip("/");HOST=rule.host;if(rule.hostJs){console.log(`检测到hostJs,准备执行...`);try{eval(rule.hostJs);rule.host=HOST.rstrip("/")}catch(e){console.log(`执行${rule.hostJs}获取host发生错误:${e.message}`)}}if(rule["模板"]==="自动"){try{let host_headers=rule["headers"]||{};let host_html=getCode(HOST,{headers:host_headers});let match_muban="";let muban_keys=Object.keys(muban).filter(it=>!/默认|短视2|采集1/.test(it));for(let muban_key of muban_keys){try{let host_data=JSON.parse(home({},host_html,muban[muban_key].class_parse));if(host_data.class&&host_data.class.length>0){match_muban=muban_key;console.log(`自动匹配模板:【${muban_key}】`);break}}catch(e){console.log(`自动匹配模板:【${muban_key}】错误:${e.message}`)}}if(match_muban){muban["自动"]=muban[match_muban];if(rule["模板修改"]&&rule["模板修改"].startsWith("js:")){eval(rule["模板修改"].replace("js:","").trim())}}else{delete rule["模板"]}}catch(e){delete rule["模板"]}}if(rule.模板&&muban.hasOwnProperty(rule.模板)){print("继承模板:"+rule.模板);rule=Object.assign(muban[rule.模板],rule)}let rule_cate_excludes=(rule.cate_exclude||"").split("|").filter(it=>it.trim());let rule_tab_excludes=(rule.tab_exclude||"").split("|").filter(it=>it.trim());rule_cate_excludes=rule_cate_excludes.concat(CATE_EXCLUDE.split("|").filter(it=>it.trim()));rule_tab_excludes=rule_tab_excludes.concat(TAB_EXCLUDE.split("|").filter(it=>it.trim()));rule.cate_exclude=rule_cate_excludes.join("|");rule.tab_exclude=rule_tab_excludes.join("|");rule.类型=rule.类型||"影视";rule.url=rule.url||"";rule.double=rule.double||false;rule.homeUrl=rule.homeUrl||"";rule.detailUrl=rule.detailUrl||"";rule.searchUrl=rule.searchUrl||"";rule.homeUrl=rule.host&&rule.homeUrl?urljoin(rule.host,rule.homeUrl):rule.homeUrl||rule.host;rule.homeUrl=cheerio.jinja2(rule.homeUrl,{rule:rule});rule.detailUrl=rule.host&&rule.detailUrl?urljoin(rule.host,rule.detailUrl):rule.detailUrl;rule.二级访问前=rule.二级访问前||"";if(rule.url.includes("[")&&rule.url.includes("]")){let u1=rule.url.split("[")[0];let u2=rule.url.split("[")[1].split("]")[0];rule.url=rule.host&&rule.url?urljoin(rule.host,u1)+"["+urljoin(rule.host,u2)+"]":rule.url}else{rule.url=rule.host&&rule.url?urljoin(rule.host,rule.url):rule.url}if(rule.searchUrl.includes("[")&&rule.searchUrl.includes("]")&&!rule.searchUrl.includes("#")){let u1=rule.searchUrl.split("[")[0];let u2=rule.searchUrl.split("[")[1].split("]")[0];rule.searchUrl=rule.host&&rule.searchUrl?urljoin(rule.host,u1)+"["+urljoin(rule.host,u2)+"]":rule.searchUrl}else{rule.searchUrl=rule.host&&rule.searchUrl?urljoin(rule.host,rule.searchUrl):rule.searchUrl}rule.timeout=rule.timeout||5e3;rule.encoding=rule.编码||rule.encoding||"utf-8";rule.search_encoding=rule.搜索编码||rule.search_encoding||"";rule.图片来源=rule.图片来源||"";rule.图片替换=rule.图片替换||"";rule.play_json=rule.hasOwnProperty("play_json")?rule.play_json:[];rule.pagecount=rule.hasOwnProperty("pagecount")?rule.pagecount:{};rule.proxy_rule=rule.hasOwnProperty("proxy_rule")?rule.proxy_rule:"";if(!rule.hasOwnProperty("sniffer")){rule.sniffer=false}rule.sniffer=rule.hasOwnProperty("sniffer")?rule.sniffer:"";rule.sniffer=!!(rule.sniffer&&rule.sniffer!=="0"&&rule.sniffer!=="false");rule.isVideo=rule.hasOwnProperty("isVideo")?rule.isVideo:"";if(rule.sniffer&&!rule.isVideo){rule.isVideo="http((?!http).){12,}?\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a|mp3)\\?.*|http((?!http).){12,}\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg|m4a|mp3)|http((?!http).)*?video/tos*|http((?!http).)*?obj/tos*"}rule.tab_remove=rule.hasOwnProperty("tab_remove")?rule.tab_remove:[];rule.tab_order=rule.hasOwnProperty("tab_order")?rule.tab_order:[];rule.tab_rename=rule.hasOwnProperty("tab_rename")?rule.tab_rename:{};if(rule.headers&&typeof rule.headers==="object"){try{let header_keys=Object.keys(rule.headers);for(let k of header_keys){if(k.toLowerCase()==="user-agent"){let v=rule.headers[k];console.log(v);if(["MOBILE_UA","PC_UA","UC_UA","IOS_UA","UA"].includes(v)){rule.headers[k]=eval(v)}}else if(k.toLowerCase()==="cookie"){let v=rule.headers[k];if(v&&v.startsWith("http")){console.log(v);try{v=fetch(v);console.log(v);rule.headers[k]=v}catch(e){console.log(`从${v}获取cookie发生错误:${e.message}`)}}}}}catch(e){console.log(`处理headers发生错误:${e.message}`)}}else{rule.headers={}}oheaders=deepCopy(rule.headers);rule_fetch_params={headers:rule.headers,timeout:rule.timeout,encoding:rule.encoding};RKEY=typeof key!=="undefined"&&key?key:"drpy_"+(rule.title||rule.host);pre();init_test()}catch(e){console.log(`init_test发生错误:${e.message}`);throw e}}let homeHtmlCache=undefined;function home(filter,home_html,class_parse){console.log("home");home_html=home_html||"";class_parse=class_parse||"";if(typeof rule.filter==="string"&&rule.filter.trim().length>0){try{let filter_json=ungzip(rule.filter.trim());rule.filter=JSON.parse(filter_json)}catch(e){rule.filter={}}}let homeObj={filter:rule.filter||false,MY_URL:rule.homeUrl,class_name:rule.class_name||"",class_url:rule.class_url||"",class_parse:class_parse||rule.class_parse||"",cate_exclude:rule.cate_exclude,home_html:home_html};return homeParse(homeObj)}function homeVod(params){console.log("homeVod");let homeVodObj={"推荐":rule.推荐,double:rule.double,homeUrl:rule.homeUrl,detailUrl:rule.detailUrl};return homeVodParse(homeVodObj)}function category(tid,pg,filter,extend){let cateObj={url:rule.url,"一级":rule.一级,tid:tid,pg:parseInt(pg),filter:filter,extend:extend};return categoryParse(cateObj)}function detail(vod_url){let orId=vod_url;let fyclass="";log("orId:"+orId);if(vod_url.indexOf("$")>-1){let tmp=vod_url.split("$");fyclass=tmp[0];vod_url=tmp[1]}let detailUrl=vod_url.split("@@")[0];let url;if(!detailUrl.startsWith("http")&&!detailUrl.includes("/")){url=rule.detailUrl.replaceAll("fyid",detailUrl).replaceAll("fyclass",fyclass)}else if(detailUrl.includes("/")){url=urljoin(rule.homeUrl,detailUrl)}else{url=detailUrl}let detailObj={orId:orId,url:url,"二级":rule.二级,"二级访问前":rule.二级访问前,detailUrl:detailUrl,fyclass:fyclass,tab_exclude:rule.tab_exclude};return detailParse(detailObj)}function play(flag,id,flags){let playObj={url:id,flag:flag,flags:flags};return playParse(playObj)}function search(wd,quick,pg){if(rule.search_encoding){if(rule.search_encoding.toLowerCase()!=="utf-8"){wd=encodeStr(wd,rule.search_encoding)}}else if(rule.encoding&&rule.encoding.toLowerCase()!=="utf-8"){wd=encodeStr(wd,rule.encoding)}let searchObj={searchUrl:rule.searchUrl,"搜索":rule.搜索,wd:wd,pg:pg||1,quick:quick};return searchParse(searchObj)}function proxy(params){if(rule.proxy_rule&&rule.proxy_rule.trim()){rule.proxy_rule=rule.proxy_rule.trim()}if(rule.proxy_rule.startsWith("js:")){rule.proxy_rule=rule.proxy_rule.replace("js:","")}let proxyObj={params:params,proxy_rule:rule.proxy_rule};return proxyParse(proxyObj)}function sniffer(){let enable_sniffer=rule.sniffer||false;if(enable_sniffer){log("开始执行辅助嗅探代理规则...")}return enable_sniffer}function isVideo(url){let t=0;let is_video;if(rule.isVideo&&rule.isVideo.trim()){is_video=rule.isVideo.trim()}if(is_video.startsWith("js:")){is_video=is_video.replace("js:","");t=1}let isVideoObj={url:url,isVideo:is_video,t:t};let result=isVideoParse(isVideoObj);if(result){log("成功执行辅助嗅探规则并检测到视频地址:\n"+rule.isVideo)}return result}function getRule(key){return key?rule[key]||"":rule}function deepCopy(_obj){return JSON.parse(JSON.stringify(_obj))}function matchesAll(str,pattern,flatten){if(!pattern.global){pattern=new RegExp(pattern.source,"g"+(pattern.ignoreCase?"i":"")+(pattern.multiline?"m":""))}var matches=[];var match;while((match=pattern.exec(str))!==null){matches.push(match)}return flatten?matches.flat():matches}function stringUtils(){Object.defineProperties(String.prototype,{replaceX:{value:function(regex,replacement){let matches=matchesAll(this,regex,true);if(matches&&matches.length>1){const hasCaptureGroup=/\$\d/.test(replacement);if(hasCaptureGroup){return this.replace(regex,m=>m.replace(regex,replacement))}else{return this.replace(regex,(m,p1)=>m.replace(p1,replacement))}}return this.replace(regex,replacement)},configurable:true,enumerable:false,writable:true},parseX:{get:function(){try{return JSON.parse(this)}catch(e){console.log(e.message);return this.startsWith("[")?[]:{}}},configurable:true,enumerable:false}})}function cut(text,start,end,method,All){let result="";let c=(t,s,e)=>{let result="";let rs=[];let results=[];try{let lr=new RegExp(String.raw`${s}`.toString());let rr=new RegExp(String.raw`${e}`.toString());const segments=t.split(lr);if(segments.length<2)return"";let cutSegments=segments.slice(1).map(segment=>{let splitSegment=segment.split(rr);return splitSegment.length<2?undefined:splitSegment[0]+e}).filter(f=>f);if(All){return`[${cutSegments.join(",")}]`}else{return cutSegments[0]}}catch(e){console.log(`Error cutting text:${e.message}`)}return result};result=c(text,start,end);stringUtils();if(method&&typeof method==="function"){result=method(result)}return result}function DRPY(){return{runMain:runMain,getRule:getRule,init:init,home:home,homeVod:homeVod,category:category,detail:detail,play:play,search:search,proxy:proxy,sniffer:sniffer,isVideo:isVideo,fixAdM3u8Ai:fixAdM3u8Ai}}export default{runMain:runMain,getRule:getRule,init:init,home:home,homeVod:homeVod,category:category,detail:detail,play:play,search:search,proxy:proxy,sniffer:sniffer,isVideo:isVideo,fixAdM3u8Ai:fixAdM3u8Ai,DRPY:DRPY}; \ No newline at end of file diff --git "a/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" "b/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" index 732fbc0c..0a607edd 100644 --- "a/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" +++ "b/spider/js/\350\256\276\347\275\256\344\270\255\345\277\203.js" @@ -397,7 +397,7 @@ var rule = { d.push(genMultiInput('play_proxy_mode', '设置播放代理模式', '默认为1,可自行配置成其他值如:2 (1 内存加速,2 磁盘加速 其他:内存加速)', images.settings)); d.push(getInput('get_play_proxy_mode', '查看播放代理模式', images.settings)); - d.push(genMultiInput('enable_dr2', '设置drpy2源启用状态', '设置为1启用drpy2脚本服务,需要壳子内置处理;设置为2启用drpy2在线接口服务(默认2,设置其他值关闭)', images.settings)); + d.push(genMultiInput('enable_dr2', '设置drpy2源启用状态', '设置为1启用drpy2脚本服务,需要壳子内置处理;设置为2启用drpy2-fast,需要壳子适配新so(默认1,设置其他值关闭)', images.settings)); d.push(getInput('get_enable_dr2', '查看drpy2源启用状态', images.settings)); d.push(genMultiInput('enable_py', '设置py源启用状态', '设置为1可启用此功能,设置为2启用T4(默认没设置也属于启动,设置其他值关闭)', images.settings)); d.push(getInput('get_enable_py', '查看py源启用状态', images.settings)); From 46e0b73dafe12a34ae0f8ef4cbbf4572c3d10a5a Mon Sep 17 00:00:00 2001 From: Taois Date: Sat, 17 Jan 2026 18:37:13 +0800 Subject: [PATCH 039/101] docs:add link --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9e7990da..d911457e 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,7 @@ pm2 restart drpys * [源动力-老](https://sourcepower.top/index) * [电竞专业反应测试](https://www.arealme.com/brain-memory-game/zh/) * [桌面启动器](https://wwbty.lanzouv.com/iDZaP3d3i5ud) +* [不知名获取网盘CK工具](http://sspa8.top:8100/pan/admin/index.php) ## AI接入 From 9beef11c886726ac6a556357b7db09363bb46fa3 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Sat, 17 Jan 2026 18:56:48 +0800 Subject: [PATCH 040/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + ...37\350\212\275\347\237\255\345\211\247.js" | 155 ------------ ...33\347\211\233\347\237\255\345\211\247.js" | 229 ------------------ ...\347\225\205\345\220\254[\345\220\254].js" | 92 +------ ...77\351\245\255\347\237\255\345\211\247.js" | 152 ------------ ...\345\260\217\350\257\264[\344\271\246].js" | 159 ++++++------ 6 files changed, 80 insertions(+), 708 deletions(-) delete mode 100644 "spider/js/\346\230\237\350\212\275\347\237\255\345\211\247.js" delete mode 100644 "spider/js/\347\211\233\347\211\233\347\237\255\345\211\247.js" delete mode 100644 "spider/js/\350\245\277\351\245\255\347\237\255\345\211\247.js" diff --git a/.gitignore b/.gitignore index 41e6c6cd..28c6287f 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,4 @@ dist /scripts/test/rsa-test.json /apps/salary/ /jx/_30wmv.js +.DS_Store diff --git "a/spider/js/\346\230\237\350\212\275\347\237\255\345\211\247.js" "b/spider/js/\346\230\237\350\212\275\347\237\255\345\211\247.js" deleted file mode 100644 index f5aed999..00000000 --- "a/spider/js/\346\230\237\350\212\275\347\237\255\345\211\247.js" +++ /dev/null @@ -1,155 +0,0 @@ -/* -@header({ - searchable: 2, - filterable: 1, - quickSearch: 1, - title: '星芽短剧', - lang: 'ds' -}) -*/ - -// http://localhost:5757/api/星芽短剧?ac=list&t=1&pg=1 -// http://localhost:5757/api/星芽短剧?ac=detail&ids=https://app.whjzjx.cn/v2/theater_parent/detail?theater_parent_id=3523 -// http://localhost:5757/api/星芽短剧?wd=龙王&pg=1 -// http://localhost:5757/api/星芽短剧?play=http://qcapp.xingya.com.cn/h265/wz_mp40905dingtianhou01.mp4?sign=4db245c4e9cd5bd3d3026e2e0f6147a6&t=674ee966&flag=星芽短剧 -var rule = { - 类型: '影视', - title: '星芽短剧', - desc: '星芽短剧纯js版本', - host: 'https://app.whjzjx.cn', - url: '/cloud/v2/theaterfyfilter', - filter_url: '/home_page?theater_class_id=fyclass&type=1&{{fl.type or "class2_ids=0"}}&page_num=fypage&page_size=24', - searchUrl: '/v3/search', - searchable: 2, - quickSearch: 1, - filterable: 1, - filter: 'H4sIAAAAAAAAA6vmUgACJUMlK4VoMBMEquEssGR2aiVQWqmksiBVSQdVKi8xNxUk93zj7qfzutFlyxJzSlNRTMZuA8I4kFlPW1e8bF6BZhbCTJCS5JzE4mKj+MyUYlsDJQx1tZha8dn3snnv0x1NxNpnQrF9T/uXvFjcSqx9phTb97xvw5Pdi1+saHjWTLSthpRb+6xjxvOl84i10IjycH3Z0PZi0VpiLTSnPFxX7n+xrYvoEKXcwqd9bU/7NxGdUCnPGS+2zni6cj/RUWhGeZAunfe0ZzfRFlKeSF+29z6fMp9YC6ngwSlznq5bQKx9xsbUKGxIzvzGVMgbfS1PdxIdkcaUR+SLCT1P180l1kJLyu1rmfhsC9Glm7ERxRY+2bWJhCg0MaTchzMnPGtEr9JxWmiBxT4UkVguVPFYrloA8HqNcnwIAAA=', - headers: { - 'User-Agent': 'okhttp/4.10.0', - 'Accept-Encoding': 'gzip', - 'x-app-id': '7', - 'platform': '1', - 'manufacturer': 'realme', - 'version_name': '3.3.1', - 'user_agent': 'Mozilla/5.0 (Linux; Android 9; RMX1931 Build/PQ3A.190605.05081124; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36', - 'dev_token': 'BFdbZBGOEgG7QDt01ldOQNNfhO2F-rv4QcugZoFZm5_3DlPJEo_bSBeJ6dW2X3eKzxxKKWz3xJCM_u5PppGMqRuYPxcsVg9a-jriWiIoPZvHMSLbcbxTFuasqgTivTY3GabW1yP57LQSsJNQfKoX1BKYGHducrhb0bTwvigfn3gE*', - 'app_version': '3.1.0.1', - 'device_platform': 'android', - 'personalized_recommend_status': '1', - 'device_type': 'RMX1931', - 'device_brand': 'realme', - 'os_version': '9', - 'channel': 'default', - 'raw_channel': 'default', - 'oaid': '', - 'msa_oaid': '', - 'uuid': 'randomUUID_8a0324bf-03c8-4789-8ef8-12d3bcff28f5', - 'device_id': '24250683a3bdb3f118dff25ba4b1cba1a', - 'ab_id': '', - 'support_h265': '1' - }, - timeout: 5000, - class_name: '剧场&热播剧&会员专享&星选好剧&新剧&阳光剧场', - class_url: '1&2&8&7&3&5', - play_parse: true, - class_parse: async () => { - }, - 预处理: async () => { - let html = await post('https://u.shytkjgs.com/user/v1/account/login', { - headers: { - 'User-Agent': 'okhttp/4.10.0', - 'Accept-Encoding': 'gzip', - 'Content-Type': 'application/x-www-form-urlencoded', - 'x-app-id': '7', - 'platform': '1', - 'manufacturer': 'realme', - 'version_name': '3.3.1', - 'user_agent': 'Mozilla/5.0 (Linux; Android 9; RMX1931 Build/PQ3A.190605.05081124; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36', - 'app_version': '3.3.1', - 'device_platform': 'android', - 'personalized_recommend_status': '1', - 'device_type': 'RMX1931', - 'device_brand': 'realme', - 'os_version': '9', - 'channel': 'default', - 'raw_channel': 'default', - 'oaid': '', - 'msa_oaid': '', - 'uuid': 'randomUUID_914e7a9b-deac-4f80-9247-db56669187df', - 'device_id': '24250683a3bdb3f118dff25ba4b1cba1a', - 'ab_id': '', - 'support_h265': '1' - }, - body: "device=24250683a3bdb3f118dff25ba4b1cba1a&install_first_open=false&first_install_time=1723214205125&last_update_time=1723214205125&report_link_url=" - }); - // log('html:', html); - html = JSON.parse(html); - try { - rule.headers['authorization'] = html.data.token - } catch (e) { - rule.headers['authorization'] = html.data.data.token - } - log('authorization:', rule.headers['authorization']); - }, - 推荐: async () => { - return [] - }, - 一级: async function (tid, pg, filter, extend) { - let {input} = this; - let d = []; - let html = await request(input, {headers: rule.headers}); - let data = JSON.parse(html).data.list; - data.forEach(it => { - let id = 'https://app.whjzjx.cn/v2/theater_parent/detail?theater_parent_id=' + it.theater.id; - d.push({ - url: id, - title: it.theater.title, - img: it.theater.cover_url, - desc: it.theater.theme, - }) - }) - return setResult(d); - }, - 二级: async function (ids) { - let {input} = this; - let urls = []; - let html = await request(input, {headers: rule.headers}); - let data = JSON.parse(html).data; - let vod = { - vod_id: input, - vod_name: data.theaters.son_title, - vod_pic: data.cover_url, - } - let playFroms = []; - let playUrls = []; - data.theaters.forEach(it => { - urls.push(it.num + '$' + encodeURIComponent(it.son_video_url)); - }) - playFroms.push('不知道倾情打造'); - vod.vod_play_from = playFroms.join('$$$'); - playUrls.push(urls.join('#')); - vod.vod_play_url = playUrls.join('$$$'); - return vod - }, - 搜索: async function (wd, quick, pg) { - let {input, KEY} = this - let d = []; - let html = await post(input, {headers: rule.headers, body: {"text": KEY}}) - let list = JSON.parse(html).data.theater.search_data; - list.forEach(it => { - let id = 'https://app.whjzjx.cn/v2/theater_parent/detail?theater_parent_id=' + it.id; - d.push({ - url: id, - title: it.title, - desc: it.total, - img: it.cover_url, - content: it.introduction, - }) - }) - return setResult(d); - }, - lazy: async function (flag, id, flags) { - let {input} = this; - return {parse: 0, url: input, js: ''} - }, -}; diff --git "a/spider/js/\347\211\233\347\211\233\347\237\255\345\211\247.js" "b/spider/js/\347\211\233\347\211\233\347\237\255\345\211\247.js" deleted file mode 100644 index 204129dc..00000000 --- "a/spider/js/\347\211\233\347\211\233\347\237\255\345\211\247.js" +++ /dev/null @@ -1,229 +0,0 @@ -/* -@header({ - searchable: 2, - filterable: 1, - quickSearch: 0, - title: '牛牛短句[短]', - '类型': '影视', - lang: 'ds' -}) -*/ - -var rule = { - title: '牛牛短句[短]', - host: 'https://new.tianjinzhitongdaohe.com', - homeUrl: '/api/v1/app/screen/screenType', - searchUrl: '/api/v1/app/search/searchMovie', - url: '/api/v1/app/screen/screenMovie?classify=fyclass&page=fypage', - headers: { - "Cache-Control": "no-cache", - "Content-Type": "application/json;charset=UTF-8", - "User-Agent": "okhttp/4.12.0" - }, - timeout: 5000, - filterable: 1, - limit: 40, - multi: 1, - searchable: 2, - play_parse: true, - search_match: true, - - class_parse: async function () { - const url = `${rule.host}/api/v1/app/screen/screenType`; - try { - const response = await request(url, { - method: 'POST', - headers: rule.headers - }); - const data = JSON.parse(response); - const classes = []; - - if (data.data && data.data[0]?.children?.[0]?.children) { - data.data[0].children[0].children.forEach(vod => { - classes.push({ - type_name: `${vod.name}`, - type_id: vod.name - }); - }); - } - - return { - class: classes, - filters: {} - }; - } catch (e) { - console.error("分类解析错误:", e); - return {class: []}; - } - }, - - 一级: async function () { - const {input, MY_PAGE} = this; - const cid = input.split('classify=')[1].split('&')[0]; - const page = MY_PAGE || 1; - const payload = JSON.stringify({ - condition: { - classify: cid, - typeId: "S1" - }, - pageNum: String(page), - pageSize: rule.limit - }); - - try { - const url = `${rule.host}/api/v1/app/screen/screenMovie`; - const response = await request(url, { - method: 'POST', - headers: rule.headers, - body: payload - }); - const data = JSON.parse(response); - const videos = []; - if (data.data?.records) { - data.data.records.forEach(vod => { - videos.push({ - title: vod.name, - img: vod.cover, - desc: `${vod.totalEpisode}集`, - url: vod.id - }); - }); - } - - return setResult(videos); - } catch (e) { - console.error("一级列表错误:", e); - return []; - } - }, - - 二级: async function () { - const { orId } = this; - let did = orId; - let bofang = ''; - let xianlu = ''; - let content = ''; - - try { - // 获取剧集列表 - const detailPayload = JSON.stringify({ - id: did, - source: 0, - typeId: "S1", - userId: "223664" - }); - - const detailUrl = `${rule.host}/api/v1/app/play/movieDetails`; - const detailResponse = await request(detailUrl, { - method: 'POST', - headers: rule.headers, - body: detailPayload - }); - - const detailData = JSON.parse(detailResponse).data || {}; - if (detailData.episodeList && detailData.episodeList.length > 0) { - const episodes = detailData.episodeList.map(ep => { - return `${ep.episode}$${did}@${ep.id}`; - }); - bofang = episodes.join('#'); - xianlu = '牛牛短句'; - content = detailData.introduce || '暂无剧情介绍'; - } - - return { - vod_name: detailData.name || '未知名称', - vod_pic: detailData.cover || '', - vod_content: content, - vod_play_from: xianlu || '暂无资源', - vod_play_url: bofang || '暂无播放地址$0' - }; - } catch (e) { - console.error("详情解析错误:", e); - return { - vod_name: '加载失败', - vod_pic: '', - vod_content: '详情加载失败,请稍后重试', - vod_play_from: '暂无资源', - vod_play_url: '暂无播放地址$0' - }; - } - }, - - 搜索: async function () { - const {KEY, MY_PAGE} = this; - const page = MY_PAGE || 1; - const payload = JSON.stringify({ - condition: { - typeId: "S1", - value: KEY - }, - pageNum: String(page), - pageSize: rule.limit - }); - - try { - const url = `${rule.host}/api/v1/app/search/searchMovie`; - const response = await request(url, { - method: 'POST', - headers: rule.headers, - body: payload - }); - const data = JSON.parse(response); - const videos = []; - - if (data.data?.records) { - data.data.records.forEach(vod => { - if (rule.search_match && !vod.name.includes(KEY)) return; - - videos.push({ - title: vod.name, - img: vod.cover, - desc: `更新时间${vod.year || '未知'}`, - url: vod.id - }); - }); - } - return setResult(videos); - } catch (e) { - console.error("搜索错误:", e); - return []; - } - }, - - lazy: async function () { - const {input} = this; - const [videoId, episodeId] = input.split('@'); - const payload = JSON.stringify({ - episodeId, - id: videoId, - source: 0, - typeId: "S1", - userId: "223664" - }); - - try { - const url = `${rule.host}/api/v1/app/play/movieDetails`; - const response = await request(url, { - method: 'POST', - headers: rule.headers, - body: payload - }); - const data = JSON.parse(response); - - return { - parse: 0, - url: data.data?.url || '', - header: { - 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36' - } - }; - } catch (e) { - console.error("播放地址获取错误:", e); - return { - parse: 0, - url: '', - header: {} - }; - } - } -}; diff --git "a/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" "b/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" index a1f2929f..d55334d0 100644 --- "a/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" +++ "b/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" @@ -1,7 +1,7 @@ /* @header({ searchable: 1, - filterable: 0, + filterable: 1, quickSearch: 0, title: '番茄畅听', author: 'EylinSir', @@ -10,92 +10,4 @@ }) */ -var rule = { - 类型: '听书', - author: 'EylinSir', - title: '番茄畅听', - host: 'https://qkfqapi.vv9v.cn', - url: '', - searchUrl: '/api/search?key=**&tab_type=2&offset=((fypage-1)*10)', - detailUrl: '/api/detail?book_id=fyid', - headers: {'User-Agent': 'UC_UA'}, - searchable: 1, - quickSearch: 0, - filterable: 0, - double: true, - play_parse: true, - limit: 12, - - action: async function (action, value) { - if (action === 'only_search') { - return '此源为纯搜索源,你直接全局搜索这个源或者使用此页面的源内搜索就好了'; - } - }, - - 推荐: async function () { - return [{ - vod_id: 'only_search', - vod_name: '纯搜索源哦!', - vod_tag: 'action', - vod_pic: this.publicUrl + '/images/icon_cookie/搜索.jpg' - }]; - }, - - 一级: async function () { - return []; - }, - - 二级: async function () { - let detailApi = `${this.host}/api/detail?book_id=${this.orId}`; - let detailJson = await request(detailApi); - let detailData = JSON.parse(detailJson); - let data = detailData.data.data; - let chaptersApi = `${this.host}/api/book?book_id=${this.orId}`; - let chaptersJson = await request(chaptersApi); - let chaptersData = JSON.parse(chaptersJson); - let bookData = chaptersData.data.data; - let list = bookData.chapterListWithVolume?.flat() || bookData.chapterList || []; - let urls = list.map(it => it.title + '$' + it.itemId + '@' + it.title).join('#'); - return { - vod_id: this.orId, - vod_name: data.book_name, - type_name: data.category, - vod_pic: data.thumb_url || data.expand_thumb_url, - vod_content: data.abstract || data.book_abstract_v2, - vod_remarks: data.sub_info, - vod_director: data.author, - vod_play_from: '番茄畅听', - vod_play_url: urls - }; - }, - - 搜索: async function () { - let {input, MY_PAGE} = this; - let html = await request(input); - let json = JSON.parse(html); - let data = json.data.search_tabs[4].data; - let d = []; - for (let it of data.filter(i => i.book_data)) { - let book = it.book_data[0]; - d.push({ - title: book.book_name, - url: book.book_id, - desc: book.author, - content: book.book_abstract || book.abstract, - pic_url: book.thumb_url - }); - } - return setResult(d); - }, - - lazy: async function () { - let {input} = this; - let parts = input.split('@'); - let itemId = parts[0]; - let toneId = '1'; - let content_url = `${this.host}/api/content?item_id=${itemId}&tab=听书&tone_id=${toneId}`; - let jsonStr = await request(content_url); - let data = JSON.parse(jsonStr); - return {parse: 0, url: data.data.content}; - } -} \ No newline at end of file +dmFyIHJ1bGUgPSB7CiAgICDnsbvlnos6ICflkKzkuaYnLAogICAgYXV0aG9yOiAnRXlsaW5TaXInLAogICAgdGl0bGU6ICfnlarojITnlYXlkKwnLAogICAgaG9zdDogJ2h0dHBzOi8vcWtmcWFwaS52djl2LmNuJywKICAgIHVybDogJy9hcGkvZGlzY292ZXI/dGFiPeWQrOS5piZ0eXBlPWZ5Y2xhc3MmZ2VuZGVyPTImZ2VucmVfdHlwZT0xJnBhZ2U9e3twYWdlfX0nLAogICAgc2VhcmNoVXJsOiAnL2FwaS9zZWFyY2g/a2V5PSoqJnRhYl90eXBlPTImb2Zmc2V0PSgoZnlwYWdlLTEpKjEwKScsCiAgICBkZXRhaWxVcmw6ICcvYXBpL2RldGFpbD9ib29rX2lkPWZ5aWQnLAogICAgaGVhZGVyczogeydVc2VyLUFnZW50JzogJ1VDX1VBJ30sCiAgICBzZWFyY2hhYmxlOiAxLAogICAgcXVpY2tTZWFyY2g6IDAsCiAgICBmaWx0ZXJhYmxlOiAxLAogICAgZG91YmxlOiB0cnVlLAogICAgcGxheV9wYXJzZTogdHJ1ZSwKICAgIGxpbWl0OiAxMiwKICAgIGNsYXNzX25hbWU6ICfnsr7lk4HlsI/or7Qm55u45aOw6K+E5LmmJuS4lueVjOWOhuWPsiblkI3okZfop6Por7sm5a2m5Lmg5oiQ6ZW/JuaIj+absuiJuuacrybnlJ/mtLvnmb7np5Em5a625bqt5pWZ6IKyJuS6uuaWh+enkeWtpiblhbbku5YnLAogICAgY2xhc3NfdXJsOiAnODk5JjQ0NSYxMiYxMzImNDQ5JjExMyY5NjAmNDUwJjQ0NyYzOScsCiAgICBmaWx0ZXI6IHsKICAgICAgICAiODk5IjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6Ijg5OSJ9LHsibiI6IumDveW4giIsInYiOiIxIn0seyJuIjoi56m/6LaKIiwidiI6IjM3In0seyJuIjoi546w5Luj6KiA5oOFIiwidiI6IjMifSx7Im4iOiLlj6Tku6PoqIDmg4UiLCJ2IjoiNSJ9LHsibiI6IuaAu+ijgSIsInYiOiIyOSJ9LHsibiI6IueOhOW5uyIsInYiOiI3In0seyJuIjoi6YeN55SfIiwidiI6IjM2In0seyJuIjoi5oKs55aRIiwidiI6IjEwIn0seyJuIjoi54G15byCIiwidiI6IjEwMCJ9LHsibiI6Iuezu+e7nyIsInYiOiIxOSJ9LHsibiI6IuenjeeUsCIsInYiOiIyMyJ9LHsibiI6IueUnOWuoCIsInYiOiI5NiJ9LHsibiI6IuWuoOWmuyIsInYiOiIzMCJ9LHsibiI6IumDveW4gueUn+a0uyIsInYiOiIyIn0seyJuIjoi6LWY5am/IiwidiI6IjI1In0seyJuIjoi5YWI5ama5ZCO54ixIiwidiI6IjI2NSJ9LHsibiI6IuWuq+aWl+WuheaWlyIsInYiOiIyNDYifSx7Im4iOiLpg73luILml6XluLgiLCJ2IjoiMjYxIn0seyJuIjoi5oiY56We6LWY5am/IiwidiI6IjI3In0seyJuIjoi56We5Yy7IiwidiI6IjI2In0seyJuIjoi5b2x6KeG5bCP6K+0IiwidiI6IjQ1In0seyJuIjoi5Zu95YaF5b2x6KeGIiwidiI6Ijk5MSJ9LHsibiI6IuWbveWkluW9seinhiIsInYiOiI5OTIifSx7Im4iOiLnsr7lk4HlsI/or7QiLCJ2IjoiOTcwIn0seyJuIjoi5oKs55aR5o6o55CGIiwidiI6IjE2NSJ9LHsibiI6IuenkeW5u+Wwj+ivtCIsInYiOiIxNjYifSx7Im4iOiLmrabkvqDlsI/or7QiLCJ2IjoiOTkzIn0seyJuIjoi546E5bm75bCP6K+0IiwidiI6Ijk3MSJ9LHsibiI6IueOsOWunuWwj+ivtCIsInYiOiI0MDAifSx7Im4iOiLmg4XmhJ/lsI/or7QiLCJ2IjoiOTcyIn0seyJuIjoi5Lyg57uf546E5bm7IiwidiI6IjI1OCJ9LHsibiI6IueOi+WmgyIsInYiOiI4NSJ9LHsibiI6IuWlh+W5u+S7meS+oCIsInYiOiIyNTkifSx7Im4iOiLokIzlrp0iLCJ2IjoiMjgifSx7Im4iOiLpg73luILohJHmtJ4iLCJ2IjoiMjYyIn0seyJuIjoi6IGM5Zy6IiwidiI6IjEyNyJ9LHsibiI6IuWroeWlsyIsInYiOiI4OCJ9LHsibiI6IumDveW4guS/ruecnyIsInYiOiIxMjQifSx7Im4iOiLlubvmg7PoqIDmg4UiLCJ2IjoiMzIifSx7Im4iOiLnpZ7osaoiLCJ2IjoiMjAifSx7Im4iOiLnqbrpl7QiLCJ2IjoiNDQifSx7Im4iOiLlhbbku5YiLCJ2IjoiMzEifSx7Im4iOiLnjoTlubvoqIDmg4UiLCJ2IjoiMjQ4In0seyJuIjoi546E5bm76ISR5rSeIiwidiI6IjI1NyJ9LHsibiI6IuWOhuWPsuWPpOS7oyIsInYiOiIyNzMifSx7Im4iOiLnp5HlubvmnKvkuJYiLCJ2IjoiOCJ9LHsibiI6IuW5tOS7oyIsInYiOiI3OSJ9LHsibiI6IuWkqeaJjSIsInYiOiI5MCJ9LHsibiI6IuWls+W8uiIsInYiOiI4NiJ9LHsibiI6IuaOqOeQhiIsInYiOiI2MSJ9LHsibiI6IuiFuem7kSIsInYiOiI5MiJ9LHsibiI6IuivuOWkqeS4h+eVjCIsInYiOiI3MSJ9LHsibiI6IuWMu+acryIsInYiOiIyNDcifSx7Im4iOiLmmJ/pmYUiLCJ2IjoiNzcifSx7Im4iOiLpibTlrp0iLCJ2IjoiMTcifSx7Im4iOiLlm6LlrqAiLCJ2IjoiOTQifSx7Im4iOiLmia7njKrlkIPomY4iLCJ2IjoiOTMifSx7Im4iOiLmrabkvqAiLCJ2IjoiMTYifSx7Im4iOiLnjrDoqIDohJHmtJ4iLCJ2IjoiMjY3In0seyJuIjoi6YO95biC56eN55SwIiwidiI6IjI2MyJ9LHsibiI6IuaXoOaVjCIsInYiOiIzODQifSx7Im4iOiLnm5flopMiLCJ2IjoiODEifSx7Im4iOiLpqaznlLIiLCJ2IjoiMjY2In0seyJuIjoi55qH5ZCOIiwidiI6Ijg0In0seyJuIjoi54m556eN5YW1IiwidiI6IjM3NSJ9LHsibiI6IuWkp+WUkCIsInYiOiI3MyJ9LHsibiI6IuWFrOS4uyIsInYiOiI4MyJ9LHsibiI6IuWoseS5kOWciCIsInYiOiI0MyJ9LHsibiI6IumdkuaiheeruemprCIsInYiOiIzODcifSx7Im4iOiLlj6ToqIDohJHmtJ4iLCJ2IjoiMjUzIn0seyJuIjoi5Y6G5Y+y6ISR5rSeIiwidiI6IjI3MiJ9LHsibiI6Iuacq+S4liIsInYiOiI2OCJ9LHsibiI6IuWJkemBkyIsInYiOiI4MCJ9LHsibiI6IueOsOiogOeUnOWuoCIsInYiOiIzOTUifSx7Im4iOiLmuLjmiI/liqjmvKsiLCJ2IjoiNTcifSx7Im4iOiLmtKrojZIiLCJ2IjoiNjYifSx7Im4iOiLlv6vnqb8iLCJ2IjoiMjQifSx7Im4iOiLmmI7mnJ0iLCJ2IjoiMTI2In0seyJuIjoi5aSW5Y2WIiwidiI6Ijc1In0seyJuIjoi5qCh6IqxIiwidiI6IjM4NSJ9LHsibiI6IuWltueIuCIsInYiOiI0MiJ9LHsibiI6IuagoeWbrSIsInYiOiI0In0seyJuIjoi5LiJ5Zu9IiwidiI6IjY3In0seyJuIjoi55u05pKtIiwidiI6IjY5In0seyJuIjoi56m/5LmmIiwidiI6IjM4MiJ9LHsibiI6Iua1t+WymyIsInYiOiI0MCJ9LHsibiI6Iue+jumjnyIsInYiOiI3OCJ9LHsibiI6IuWPjea0viIsInYiOiIzNjkifSx7Im4iOiLnjrDoqIDlpI3ku4ciLCJ2IjoiMjY4In0seyJuIjoi6KW/5ri46KGN55SfIiwidiI6IjM3MyJ9LHsibiI6IuaxgueUnyIsInYiOiIzNzkifSx7Im4iOiLmsJHlm70iLCJ2IjoiMzkwIn0seyJuIjoi5a625bqtIiwidiI6IjEyNSJ9LHsibiI6IuWtpumcuCIsInYiOiI4MiJ9LHsibiI6Iueah+WPlCIsInYiOiI4NyJ9LHsibiI6IuWuoOeJqSIsInYiOiI3NCJ9LHsibiI6IuaXoENQIiwidiI6IjM5MiJ9LHsibiI6IuWls+aJrueUt+ijhSIsInYiOiIzODgifSx7Im4iOiLnvZHmuLgiLCJ2IjoiMzcyIn0seyJuIjoi55eF5aiHIiwidiI6IjM4MCJ9LHsibiI6IueyvueBtSIsInYiOiI4OSJ9LHsibiI6IuiZkOaWhyIsInYiOiI5NSJ9LHsibiI6IumDveW4gumdkuaYpSIsInYiOiIzOTYifSx7Im4iOiLmuIXnqb8iLCJ2IjoiNzYifV19XSwKICAgICAgICAiNDQ1IjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjQ0NSJ9LHsibiI6IumDreW+t+e6siIsInYiOiIxMjgifSx7Im4iOiLnlLDov57lhYMiLCJ2IjoiMjAzIn0seyJuIjoi5YiY5YWw6IqzIiwidiI6IjIwMiJ9LHsibiI6IuWwj+WTgSIsInYiOiIxMTQifSx7Im4iOiLoooHpmJTmiJAiLCJ2IjoiMjA0In0seyJuIjoi5Y2V55Sw6IqzIiwidiI6IjIwMSJ9LHsibiI6IuivhOS5piIsInYiOiIxMTAifSx7Im4iOiLnm7jlo7AiLCJ2IjoiMTExIn1dfV0sCiAgICAgICAgIjEyIjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjEyIn0seyJuIjoi6a2P5pmL5Y2X5YyX5pydIiwidiI6IjIwOSJ9LHsibiI6IuenpuaxiSIsInYiOiIyMDgifSx7Im4iOiLkuJbnlYzlj7IiLCJ2IjoiMjE0In0seyJuIjoi5ZSQ5a6LIiwidiI6IjIxMCJ9LHsibiI6IuaYjua4hSIsInYiOiIyMTEifSx7Im4iOiLov5HnjrDku6MiLCJ2IjoiMjEzIn0seyJuIjoi5Lit5Zu95Y+yIiwidiI6IjIxMiJ9LHsibiI6IuaImOS6ieWPsiIsInYiOiIyMDYifSx7Im4iOiLlkI3kurrkvKAiLCJ2IjoiMjA3In0seyJuIjoi5Lit5Zu95Y6G5Y+yIiwidiI6IjQwMiJ9LHsibiI6IuS4lueVjOWOhuWPsiIsInYiOiI0MDMifSx7Im4iOiLljoblj7LlsI/or7QiLCJ2IjoiOTg4In0seyJuIjoi5Y6G5Y+y5paH5YyWIiwidiI6IjI0MSJ9XX1dLAogICAgICAgICIxMzIiOiBbe2tleTogInR5cGUiLCBuYW1lOiAi57G75Z6LIiwgdmFsdWU6IFt7Im4iOiLlhajpg6giLCJ2IjoiMTMyIn0seyJuIjoi5oiY5LqJIiwidiI6Ijk3In0seyJuIjoi5Lit5Zu95ZCN6JGXIiwidiI6Ijk4In0seyJuIjoi5aSW5Zu95ZCN6JGXIiwidiI6Ijk5In0seyJuIjoi57uP566h5Yqx5b+XIiwidiI6IjI0MiJ9LHsibiI6IuS6uueJqeS8oOiusCIsInYiOiI0MDkifSx7Im4iOiLnu4/lhbjmloflraYiLCJ2IjoiMjQzIn0seyJuIjoi6Z2S5pil5paH5a2mIiwidiI6IjE2OCJ9LHsibiI6IuaImOS6ieWGm+aXhSIsInYiOiI5NzMifV19XSwKICAgICAgICAiNDQ5IjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjQ0OSJ9LHsibiI6IuazleW+iyIsInYiOiIxNDIifSx7Im4iOiLlv4PnkIYiLCJ2IjoiMTQ2In0seyJuIjoi5b+D55CG5a2mIiwidiI6IjQwNyJ9LHsibiI6IuWwkeWEv+W/g+eQhiIsInYiOiI5ODYifSx7Im4iOiLlv4PnkIbnlpfmhIgiLCJ2IjoiOTk0In0seyJuIjoi5oqV6LWE55CG6LSiIiwidiI6IjE0MyJ9LHsibiI6IuiBjOS4muiBjOWcuiIsInYiOiIxNDUifSx7Im4iOiLnu4/nrqHllYbkuJoiLCJ2IjoiMjM4In0seyJuIjoi5rKf6YCa6KGo6L6+IiwidiI6IjE0NCJ9LHsibiI6IuWKseW/l+aIkOWKnyIsInYiOiIyMzkifV19XSwKICAgICAgICAiMTEzIjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjExMyJ9LHsibiI6IuS6rOWJpyIsInYiOiIxNzEifSx7Im4iOiLotorliaciLCJ2IjoiMTcyIn0seyJuIjoi6buE5qKF5oiPIiwidiI6IjE3MyJ9LHsibiI6IuivhOWJpyIsInYiOiIxNzQifSx7Im4iOiLosavliaciLCJ2IjoiMTc1In0seyJuIjoi5piG5puyIiwidiI6IjE3NiJ9LHsibiI6IuiJuuacryIsInYiOiIxMzQifSx7Im4iOiLoibrmnK/mlofljJYiLCJ2IjoiOTQ1In0seyJuIjoi6Z+z5LmQ6Iie6LmIIiwidiI6Ijk0NiJ9LHsibiI6Iue7mOeUuyIsInYiOiI5NTkifSx7Im4iOiLmkYTlvbEiLCJ2IjoiOTYxIn0seyJuIjoi6Ym06LWP55CG6K66IiwidiI6Ijk2MiJ9XX1dLAogICAgICAgICI5NjAiOiBbe2tleTogInR5cGUiLCBuYW1lOiAi57G75Z6LIiwgdmFsdWU6IFt7Im4iOiLlhajpg6giLCJ2IjoiOTYwIn0seyJuIjoi576O6aOf54O56aWqIiwidiI6IjI0MCJ9LHsibiI6IuaXhea4uCIsInYiOiIxNTgifSx7Im4iOiLlgaXlurflhbvnlJ8iLCJ2IjoiMTU5In0seyJuIjoi6L+Q5Yqo5YGl6LqrIiwidiI6IjQxNyJ9LHsibiI6IuaXtuWwmue+juWmhiIsInYiOiI0MTgifSx7Im4iOiLnvo7po5/kvJHpl7IiLCJ2IjoiNDE5In0seyJuIjoi5a625bGF5peF5ri4IiwidiI6IjQyMCJ9LHsibiI6IumjjuawtOWNoOWNnCIsInYiOiI0MjEifSx7Im4iOiLnmb7np5HluLjor4YiLCJ2IjoiOTYzIn0seyJuIjoi55Sf5rS75oOF5oSfIiwidiI6Ijk2NCJ9XX1dLAogICAgICAgICI0NTAiOiBbe2tleTogInR5cGUiLCBuYW1lOiAi57G75Z6LIiwgdmFsdWU6IFt7Im4iOiLlhajpg6giLCJ2IjoiNDUwIn0seyJuIjoi5Lqy5a2QIiwidiI6IjQ0NyJ9LHsibiI6IuWpmuWnuyIsInYiOiIyMzQifSx7Im4iOiLnvo7mlociLCJ2IjoiMjMwIn0seyJuIjoi5aSc6K+dIiwidiI6IjIzMiJ9LHsibiI6IuWls+aApyIsInYiOiIyMzEifSx7Im4iOiLlv4PnkIblgaXlurciLCJ2IjoiMjMzIn0seyJuIjoi5oOF5oSf5pWF5LqLIiwidiI6IjIyOSJ9LHsibiI6IuS6p+WQjuaKpOeQhiIsInYiOiIyMjYifSx7Im4iOiLlhL/nq6Xoi7Hor60iLCJ2IjoiMjIyIn0seyJuIjoi5a2V5pyf5L+d5YGlIiwidiI6IjIyNyJ9LHsibiI6IuS6suWtkOWBpeW6tyIsInYiOiIyMjgifSx7Im4iOiLnp5Hmma4iLCJ2IjoiMjIzIn0seyJuIjoi5Zu95a2m5Y6G5Y+yIiwidiI6IjIyNCJ9LHsibiI6IuiDjuaVmeaXqeaVmSIsInYiOiIyMjUifSx7Im4iOiLlhL/nq6XmloflraYiLCJ2IjoiMjIwIn1dfV0sCiAgICAgICAgIjQ0NyI6IFt7a2V5OiAidHlwZSIsIG5hbWU6ICLnsbvlnosiLCB2YWx1ZTogW3sibiI6IuWFqOmDqCIsInYiOiI0NDcifSx7Im4iOiLnp5HlrabmioDmnK8iLCJ2IjoiMTAwMCJ9LHsibiI6IuiHqueEtuenkeWtpiIsInYiOiIxMzYifSx7Im4iOiLkvZvlraYiLCJ2IjoiMTE1In0seyJuIjoi56S+56eRIiwidiI6IjIzNyJ9LHsibiI6IuWbveWtpiIsInYiOiIxMTYifSx7Im4iOiLmlaPmlofmiI/liaciLCJ2IjoiMjM2In0seyJuIjoi5paH5YyWIiwidiI6IjExOCJ9LHsibiI6IuaKgOacryIsInYiOiI5NjkifSx7Im4iOiLnp5HlraYiLCJ2IjoiOTc5In0seyJuIjoi5bel5LiaIiwidiI6Ijk4MCJ9LHsibiI6IuWGnOael+eJp+a4lCIsInYiOiI5ODEifSx7Im4iOiLorqHnrpfmnLoiLCJ2IjoiOTgyIn0seyJuIjoi5bu6562R5Zut5p6XIiwidiI6Ijk4MyJ9XX1dLAogICAgICAgICIzOSI6IFt7a2V5OiAidHlwZSIsIG5hbWU6ICLnsbvlnosiLCB2YWx1ZTogW3sibiI6IuS6jOasoeWFgyIsInYiOiIzOSJ9LHsibiI6IuWoseS5kCIsInYiOiIxMjEifSx7Im4iOiLnuqrlvZUiLCJ2IjoiMTMzIn0seyJuIjoi5paw6Ze7IiwidiI6IjQ0NiJ9XX1dCiAgICB9LAoKICAgIOS4gOe6pzogYXN5bmMgZnVuY3Rpb24gKHRpZCwgcGcsIGZpbHRlciwgZXh0ZW5kKSB7CiAgICAgICAgbGV0IHBhZ2UgPSBwZyB8fCAxOwogICAgICAgIGxldCB0eXBlSWQgPSAoZXh0ZW5kICYmIGV4dGVuZC50eXBlKSA/IGV4dGVuZC50eXBlIDogdGlkOwogICAgICAgIGxldCBmaW5hbFVybCA9IGAke3RoaXMuaG9zdH0vYXBpL2Rpc2NvdmVyP3RhYj3lkKzkuaYmdHlwZT0ke3R5cGVJZH0mZ2VuZGVyPTImZ2VucmVfdHlwZT0xJnBhZ2U9JHtwYWdlfWA7CiAgICAgICAgbGV0IGpzb24gPSBhd2FpdCByZXF1ZXN0KGZpbmFsVXJsKTsKICAgICAgICBsZXQgZGF0YSA9IEpTT04ucGFyc2UoanNvbik7CiAgICAgICAgbGV0IGJvb2tfbGlzdCA9IGRhdGEuY29kZSA9PT0gMjAwID8gZGF0YS5kYXRhIDogW107CiAgICAgICAgbGV0IGQgPSBbXTsKICAgICAgICBib29rX2xpc3QuZm9yRWFjaCgoaXQpID0+IHsKICAgICAgICAgICAgZC5wdXNoKHsKICAgICAgICAgICAgICAgIHRpdGxlOiBpdC5ib29rX25hbWUgfHwgaXQuQm9va05hbWUsCiAgICAgICAgICAgICAgICB1cmw6IGl0LmJvb2tfaWQgfHwgaXQuQm9va0lkLAogICAgICAgICAgICAgICAgZGVzYzogaXQuYXV0aG9yIHx8IGl0LkF1dGhvciwKICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGl0LmFic3RyYWN0IHx8IGl0LkFic3RyYWN0IHx8IGl0LmJvb2tfYWJzdHJhY3RfdjIsCiAgICAgICAgICAgICAgICBwaWNfdXJsOiBpdC50aHVtYl91cmwgfHwgaXQuVGh1bWJVUkwgfHwgaXQuYXVkaW9fdGh1bWJfdXJpCiAgICAgICAgICAgIH0pOwogICAgICAgIH0pOwoKICAgICAgICByZXR1cm4gc2V0UmVzdWx0KGQpOwogICAgfSwKCiAgICDkuoznuqc6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgZGV0YWlsQXBpID0gYCR7dGhpcy5ob3N0fS9hcGkvZGV0YWlsP2Jvb2tfaWQ9JHt0aGlzLm9ySWR9YDsKICAgICAgICBsZXQgZGV0YWlsSnNvbiA9IGF3YWl0IHJlcXVlc3QoZGV0YWlsQXBpKTsKICAgICAgICBsZXQgZGV0YWlsRGF0YSA9IEpTT04ucGFyc2UoZGV0YWlsSnNvbik7CiAgICAgICAgbGV0IGRhdGEgPSBkZXRhaWxEYXRhLmRhdGEuZGF0YTsKICAgICAgICBsZXQgY2hhcHRlcnNBcGkgPSBgJHt0aGlzLmhvc3R9L2FwaS9ib29rP2Jvb2tfaWQ9JHt0aGlzLm9ySWR9YDsKICAgICAgICBsZXQgY2hhcHRlcnNKc29uID0gYXdhaXQgcmVxdWVzdChjaGFwdGVyc0FwaSk7CiAgICAgICAgbGV0IGNoYXB0ZXJzRGF0YSA9IEpTT04ucGFyc2UoY2hhcHRlcnNKc29uKTsKICAgICAgICBsZXQgYm9va0RhdGEgPSBjaGFwdGVyc0RhdGEuZGF0YS5kYXRhOwogICAgICAgIGxldCBsaXN0ID0gYm9va0RhdGEuY2hhcHRlckxpc3RXaXRoVm9sdW1lPy5mbGF0KCkgfHwgYm9va0RhdGEuY2hhcHRlckxpc3QgfHwgW107CiAgICAgICAgbGV0IHVybHMgPSBsaXN0Lm1hcChpdCA9PiBpdC50aXRsZSArICckJyArIGl0Lml0ZW1JZCArICdAJyArIGl0LnRpdGxlKS5qb2luKCcjJyk7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgdm9kX2lkOiB0aGlzLm9ySWQsCiAgICAgICAgICAgIHZvZF9uYW1lOiBkYXRhLmJvb2tfbmFtZSwKICAgICAgICAgICAgdHlwZV9uYW1lOiBkYXRhLmNhdGVnb3J5LAogICAgICAgICAgICB2b2RfcGljOiBkYXRhLnRodW1iX3VybCB8fCBkYXRhLmV4cGFuZF90aHVtYl91cmwsCiAgICAgICAgICAgIHZvZF9jb250ZW50OiBkYXRhLmFic3RyYWN0IHx8IGRhdGEuYm9va19hYnN0cmFjdF92MiwKICAgICAgICAgICAgdm9kX3JlbWFya3M6IGRhdGEuc3ViX2luZm8sCiAgICAgICAgICAgIHZvZF9kaXJlY3RvcjogZGF0YS5hdXRob3IsCiAgICAgICAgICAgIHZvZF9wbGF5X2Zyb206ICfnlarojITnlYXlkKwnLAogICAgICAgICAgICB2b2RfcGxheV91cmw6IHVybHMKICAgICAgICB9OwogICAgfSwKCiAgICDmkJzntKI6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQge2lucHV0fSA9IHRoaXM7CiAgICAgICAgbGV0IGh0bWwgPSBhd2FpdCByZXF1ZXN0KGlucHV0KTsKICAgICAgICBsZXQganNvbiA9IEpTT04ucGFyc2UoaHRtbCk7CiAgICAgICAgbGV0IGRhdGEgPSBqc29uLmRhdGEuc2VhcmNoX3RhYnNbNF0uZGF0YTsKICAgICAgICBsZXQgZCA9IFtdOwogICAgICAgIGZvciAobGV0IGl0IG9mIGRhdGEuZmlsdGVyKGkgPT4gaS5ib29rX2RhdGEpKSB7CiAgICAgICAgICAgIGxldCBib29rID0gaXQuYm9va19kYXRhWzBdOwogICAgICAgICAgICBkLnB1c2goewogICAgICAgICAgICAgICAgdGl0bGU6IGJvb2suYm9va19uYW1lLAogICAgICAgICAgICAgICAgdXJsOiBib29rLmJvb2tfaWQsCiAgICAgICAgICAgICAgICBkZXNjOiBib29rLmF1dGhvciwKICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGJvb2suYm9va19hYnN0cmFjdCB8fCBib29rLmFic3RyYWN0LAogICAgICAgICAgICAgICAgcGljX3VybDogYm9vay50aHVtYl91cmwKICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZXRSZXN1bHQoZCk7CiAgICB9LAoKICAgIGxhenk6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQge2lucHV0fSA9IHRoaXM7CiAgICAgICAgbGV0IHBhcnRzID0gaW5wdXQuc3BsaXQoJ0AnKTsKICAgICAgICBsZXQgaXRlbUlkID0gcGFydHNbMF07CiAgICAgICAgbGV0IHRvbmVJZCA9ICcxJzsKICAgICAgICBsZXQgY29udGVudF91cmwgPSBgJHt0aGlzLmhvc3R9L2FwaS9jb250ZW50P2l0ZW1faWQ9JHtpdGVtSWR9JnRhYj3lkKzkuaYmdG9uZV9pZD0ke3RvbmVJZH1gOwogICAgICAgIGxldCBqc29uU3RyID0gYXdhaXQgcmVxdWVzdChjb250ZW50X3VybCk7CiAgICAgICAgbGV0IGRhdGEgPSBKU09OLnBhcnNlKGpzb25TdHIpOwogICAgICAgIHJldHVybiB7cGFyc2U6IDAsIHVybDogZGF0YS5kYXRhLmNvbnRlbnR9OwogICAgfQp9Ow== \ No newline at end of file diff --git "a/spider/js/\350\245\277\351\245\255\347\237\255\345\211\247.js" "b/spider/js/\350\245\277\351\245\255\347\237\255\345\211\247.js" deleted file mode 100644 index 3a1c8a7b..00000000 --- "a/spider/js/\350\245\277\351\245\255\347\237\255\345\211\247.js" +++ /dev/null @@ -1,152 +0,0 @@ -/* -@header({ - searchable: 2, - filterable: 1, - quickSearch: 0, - title: '西饭短剧[短]', - '类型': '影视', - lang: 'ds' -}) -*/ - -var rule = { - title: '西饭短剧[短]', - host: 'https://xifan-api-cn.youlishipin.com', - homeUrl: '/xifan/drama/portalPage?reqType=duanjuCategory&version=2001001&androidVersionCode=28', - searchUrl: '**', - url: '/xifan/drama/portalPage?reqType=aggregationPage&offset=fypage&categoryId=fyclass', - headers: { - 'User-Agent': 'okhttp/3.12.11', - }, - timeout: 5000, - filterable: 1, - limit: 30, - multi: 1, - searchable: 2, - play_parse: true, - search_match: true, - - class_parse: async function () { - let {input} = this; - let html = await request(input); - let classes = []; - let filters = {}; - let data = JSON.parse(html).result.elements[0].contents; - data.forEach((it) => { - const categoryItemVo = it.categoryItemVo || {}; - const typeName = categoryItemVo.oppoCategory; - const typeId = categoryItemVo.categoryId; - const subCategories = categoryItemVo.subCategories || []; - - // 只提取 type 为 duanjuCategory 的作为主分类 - if (it.type && it.type.includes("duanjuCategory")) { - classes.push({ - type_name: typeName, - type_id: `${typeId}@${typeName}`, - }); - } - - // 其他作为筛选条件 - if (subCategories.length > 0) { - filters[typeName] = { - key: categoryItemVo.categoryId, - name: categoryItemVo.oppoCategory, - value: subCategories.map(sub => ({ - n: sub.oppoCategory, - v: `${sub.oppoCategory}@${sub.categoryId}` - })) - }; - } - }); - // 设置筛选条件 - return { - class: classes, - filters: filters - }; - }, - - 一级: async function () { - let {input,MY_PAGE} = this; - const typeId = input.split('categoryId=')[1].split('@')[0]; - const typeName = input.split('categoryId=')[1].split('@')[1]; - let page = (MY_PAGE - 1) * rule.limit; - let current_timestamp = Math.floor(Date.now() / 1000); - let url = `${rule.host}/xifan/drama/portalPage?reqType=aggregationPage&offset=${page}&categoryId=${typeId}&quickEngineVersion=-1&scene=&categoryNames=${encodeURIComponent(typeName)}&categoryVersion=1&density=1.5&pageID=page_theater&version=2001001&androidVersionCode=28&requestId=${current_timestamp}aa498144140ef297&appId=drama&teenMode=false&userBaseMode=false&session=eyJpbmZvIjp7InVpZCI6IiIsInJ0IjoiMTc0MDY1ODI5NCIsInVuIjoiT1BHXzFlZGQ5OTZhNjQ3ZTQ1MjU4Nzc1MTE2YzFkNzViN2QwIiwiZnQiOiIxNzQwNjU4Mjk0In19&feedssession=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dHlwIjowLCJidWlkIjoxNjMzOTY4MTI2MTQ4NjQxNTM2LCJhdWQiOiJkcmFtYSIsInZlciI6MiwicmF0IjoxNzQwNjU4Mjk0LCJ1bm0iOiJPUEdfMWVkZDk5NmE2NDdlNDUyNTg3NzUxMTZjMWQ3NWI3ZDAiLCJpZCI6IjNiMzViZmYzYWE0OTgxNDQxNDBlZjI5N2JkMDY5NGNhIiwiZXhwIjoxNzQxMjYzMDk0LCJkYyI6Imd6cXkifQ.JS3QY6ER0P2cQSxAE_OGKSMIWNAMsYUZ3mJTnEpf-Rc`; - - let d = []; - let html = await request(url, { headers: rule.headers }); - let data = JSON.parse(html).result.elements; - data.forEach((soup) => { - soup.contents.forEach((vod) => { - let dj = vod.duanjuVo; - d.push({ - title: dj.title, - img: dj.coverImageUrl, - desc: dj.total + '集', - url: `${dj.duanjuId}#${dj.source}` - }); - }); - }); - - return setResult(d); - }, - - 二级: async function () { - let {orId} = this; - let [duanjuId, source] = orId.split("#"); - let url = `${rule.host}/xifan/drama/getDuanjuInfo?duanjuId=${duanjuId}&source=${source}&openFrom=homescreen&type=&pageID=page_inner_flow&density=1.5&version=2001001&androidVersionCode=28&requestId=1740658944980aa498144140ef297&appId=drama&teenMode=false&userBaseMode=false&session=eyJpbmZvIjp7InVpZCI6IiIsInJ0IjoiMTc0MDY1ODI5NCIsInVuIjoiT1BHXzFlZGQ5OTZhNjQ3ZTQ1MjU4Nzc1MTE2YzFkNzViN2QwIiwiZnQiOiIxNzQwNjU4Mjk0In19&feedssession=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dHlwIjowLCJidWlkIjoxNjMzOTY4MTI2MTQ4NjQxNTM2LCJhdWQiOiJkcmFtYSIsInZlciI6MiwicmF0IjoxNzQwNjU4Mjk0LCJ1bm0iOiJPUEdfMWVkZDk5NmE2NDdlNDUyNTg3NzUxMTZjMWQ3NWI3ZDAiLCJpZCI6IjNiMzViZmYzYWE0OTgxNDQxNDBlZjI5N2JkMDY5NGNhIiwiZXhwIjoxNzQxMjYzMDk0LCJkYyI6Imd6cXkifQ.JS3QY6ER0P2cQSxAE_OGKSMIWNAMsYUZ3mJTnEpf-Rc`; - - let response = await request(url, { headers: rule.headers }); - let data = JSON.parse(response).result; - VOD = { - vod_name: data.title, - vod_pic: data.coverImageUrl, - vod_content: data.desc || '未知', - vod_remarks: data.updateStatus === 'over' ? `${data.total}集 已完结` : `更新${data.total}集` - }; - - let playUrls = []; - data.episodeList.forEach((ep) => { - playUrls.push(`${ep.index}$${ep.playUrl}`); - }); - - VOD.vod_play_from = '西饭短剧'; - VOD.vod_play_url = playUrls.join("#"); - return VOD; - }, - - 搜索: async function () { - let {input,MY_PAGE,KEY} = this; - let d = []; - let current_timestamp = Math.floor(Date.now() / 1000); - let url = `${rule.host}/xifan/search/getSearchList?keyword=${KEY}84&pageIndex=${MY_PAGE}&version=2001001&androidVersionCode=28&requestId=${current_timestamp}ea3a14bc0317d76f&appId=drama&teenMode=false&userBaseMode=false&session=eyJpbmZvIjp7InVpZCI6IiIsInJ0IjoiMTc0MDY2ODk4NiIsInVuIjoiT1BHX2U5ODQ4NTgzZmM4ZjQzZTJhZjc5ZTcxNjRmZTE5Y2JjIiwiZnQiOiIxNzQwNjY4OTg2In19&feedssession=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dHlwIjowLCJidWlkIjoxNjM0MDU3ODE4OTgxNDk5OTA0LCJhdWQiOiJkcmFtYSIsInZlciI6MiwicmF0IjoxNzQwNjY4OTg2LCJ1bm0iOiJPUEdfZTk4NDg1ODNmYzhmNDNlMmFmNzllNzE2NGZlMTljYmMiLCJpZCI6ImVhZGE1NmEyZWEzYTE0YmMwMzE3ZDc2ZmVjODJjNzc3IiwiZXhwIjoxNzQxMjczNzg2LCJkYyI6ImJqaHQifQ.IwuI0gK077RF4G10JRxgxx4GCG502vR8Z0W9EV4kd-c`; - - let html = await request(url, {headers: rule.headers }); - let data = JSON.parse(html).result.elements; - data.forEach((soup) => { - soup.contents.forEach((vod) => { - let dj = vod.duanjuVo; - let name = dj.title.replace(/<\/?tag>/g, ""); - if (rule.search_match && !new RegExp(KEY, "i").test(name)) { - return; - } - - d.push({ - title: name, - img: dj.coverImageUrl, - desc: dj.total + '集', - url: `${dj.duanjuId}#${dj.source}` - }); - }); - }); - - return setResult(d); - }, - lazy: async function () { - let {input} = this; - return { - parse: 0, - url: input - }; - }, -} diff --git "a/spider/js/\351\241\266\347\202\271\345\260\217\350\257\264[\344\271\246].js" "b/spider/js/\351\241\266\347\202\271\345\260\217\350\257\264[\344\271\246].js" index 99a113b4..824f2580 100644 --- "a/spider/js/\351\241\266\347\202\271\345\260\217\350\257\264[\344\271\246].js" +++ "b/spider/js/\351\241\266\347\202\271\345\260\217\350\257\264[\344\271\246].js" @@ -10,85 +10,80 @@ */ var rule = { - 类型: '小说',//影视|听书|漫画|小说 - title: '顶点小说[书]', - host: 'https://www.23ddw.cc/', - // 编码: 'gb18030', - 编码: 'utf-8', - url: '/class/fyclass_fypage/', - - // searchUrl: '/modules/article/search.php?searchkey=**&page=fypage', - searchUrl: '/searchss/?searchkey=**&page=fypage', - searchable: 2, - quickSearch: 0, - filterable: 1, - filter: '', - filter_url: '', - filter_def: {}, - headers: { - 'User-Agent': 'PC_UA', - }, - timeout: 5000, - hikerListCol: "text_1", - hikerClassListCol: "text_1", - class_name: '全本', - class_url: '0', - class_parse: '.nav&&ul&&li;a&&Text;a&&href;class/(.*?)_', - cate_exclude: '', - play_parse: true, - lazy: $js.toString(async () => { - log('input:', input); - let html = await request(input); - let title = pdfh(html, '.bookname&&Text'); - let content = pdfh(html, '#content&&Html').replace(/\n/g, "").split("
    ").filter(v => v).slice(0).join("\n").replace(/ /g, ' '); - let ret = JSON.stringify({ - title, - content - }); - input = {parse: 0, url: 'novel://' + ret, js: ''}; - return input; - }), - double: false, - 推荐: '#newscontent&&ul&&li;.s2&&Text;;.s5&&Text;a&&href', - 一级: $js.toString(async () => { - let d = []; - if (MY_CATE == '0') { - input = urljoin(rule.host, '/quanben/' + MY_PAGE); - let html = await request(input); - let lis = pdfa(html, 'table.grid&&tr:gt(0)'); - lis.forEach(it => { - d.push({ - title: pdfh(it, 'a&&Text'), - desc: pdfh(it, 'a:eq(1)&&Text'), - img: "", - url: pd(it, 'a&&href', MY_URL), - }); - }); - } else { - let html = await request(input.split('#')[0]); - let lis = pdfa(html, '#newscontent&&ul&&li'); - lis.forEach(it => { - d.push({ - title: pdfh(it, '.s2&&Text'), - desc: pdfh(it, '.s5&&Text'), - img: "", - url: pd(it, 'a&&href', MY_URL), - }); - }); - } - return setResult(d); - }), - 二级: { - title: 'h1&&Text', - img: '#fmimg&&img&&src', - desc: '#info&&p:eq(-1)&&Text', - content: '#intro&&p&&Text', - tabs: '#list&&dt', - lists: '#list&&a', - tab_text: 'dd&&Text', - list_text: 'body&&Text', - list_url: 'a&&href', - list_url_prefix: '', - }, - 搜索: '#hotcontent&&.item;a&&title;img&&data-original;.blue.visible-xs&&Text;a&&href;dd&&Text', -} \ No newline at end of file + 类型: '小说', + title: '顶点小说[书]', + host: 'https://www.23ddw.cc/', + 编码: 'utf-8', + url: '/class/fyclass_fypage/', + searchUrl: '/searchss/?searchkey=**&page=fypage', + searchable: 2, + quickSearch: 0, + filterable: 1, + filter: '', + filter_url: '', + filter_def: {}, + headers: { 'User-Agent': 'PC_UA' }, + timeout: 5000, + hikerListCol: "text_1", + hikerClassListCol: "text_1", + class_name: '全本', + class_url: '0', + class_parse: '.nav&&ul&&li;a&&Text;a&&href;class/(.*?)_', + cate_exclude: '', + play_parse: true, + lazy: $js.toString(async () => { + log('input:', input); + let html = await request(input); + let title = pdfh(html, '.bookname&&Text'); + let content = pdfh(html, '#content&&Html') || ''; + if (content) { + content = content + .replace(/]*?>.*?<\/script>/gs, '') + .replace(/<\/p>/g, '\n\n') + .replace(//gi, '\n') + .replace(/<[^>]+>/g, '') + .replace(/ /g, ' ') + .replace(/\n\s*\n/g, '\n\n') + .trim(); + } + input = { parse: 0, url: `novel://${JSON.stringify({ title, content })}`, js: '' }; + return input; + }), + double: false, + 一级: $js.toString(async () => { + let d = []; + let url = MY_CATE === '0' + ? urljoin(rule.host, `/quanben/${MY_PAGE}`) + : input.split('#')[0].replace(/_[0-9]+\.html/, '') + `_${MY_PAGE}.html`; + let html = await request(url); + let lis = pdfa(html, '#newscontent ul li') || pdfa(html, '.item'); + lis.forEach(it => { + let title = pdfh(it, 'dt&&Text') || pdfh(it, '.s2&&Text'); + let author = pdfh(it, '.btm a&&Text') || pdfh(it, '.s4&&Text'); + let lastChapter = pdfh(it, '.s3&&Text'); + let img = pdfh(it, 'img&&data-original') + ? pd(it, 'img&&data-original', rule.host) + : (pdfh(it, 'img&&src') ? pd(it, 'img&&src', rule.host) : ''); + d.push({ + title, + desc: `${author} | ${lastChapter}`, + img, + url: pd(it, 'a&&href', rule.host) + }); + }); + return setResult(d); + }), + 二级: { + title: 'h1&&Text', + img: '#fmimg&&img&&data-original;#fmimg&&img&&src', + desc: '#info&&p:eq(-1)&&Text', + content: '#intro&&p&&Text', + tabs: '#list&&dt', + lists: '#list&&a', + tab_text: 'dd&&Text', + list_text: 'body&&Text', + list_url: 'a&&href', + list_url_prefix: '', + }, + 搜索: '#hotcontent&&.item;#newscontent ul li;a&&title;img&&data-original;.btm a&&Text;.blue.visible-xs&&Text;a&&href;dd&&Text;.s2&&Text;.s4&&Text;.s3&&Text' +}; \ No newline at end of file From b6a8616c72d907a66516bac53c9189a32889cb7e Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Sat, 17 Jan 2026 18:58:40 +0800 Subject: [PATCH 041/101] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\347\237\255\345\211\247[\347\237\255].js" | 0 ...\347\237\255\345\211\247[\347\237\255].js" | 155 ++++++++++++ ...\347\237\255\345\211\247[\347\237\255].js" | 229 ++++++++++++++++++ ...\347\237\255\345\211\247[\347\237\255].js" | 152 ++++++++++++ ...\347\237\255\345\211\247[\347\237\255].js" | 0 5 files changed, 536 insertions(+) rename "spider/js/\344\270\203\347\214\253\347\237\255\345\211\247.js" => "spider/js/\344\270\203\347\214\253\347\237\255\345\211\247[\347\237\255].js" (100%) create mode 100644 "spider/js/\346\230\237\350\212\275\347\237\255\345\211\247[\347\237\255].js" create mode 100644 "spider/js/\347\211\233\347\211\233\347\237\255\345\211\247[\347\237\255].js" create mode 100644 "spider/js/\350\245\277\351\245\255\347\237\255\345\211\247[\347\237\255].js" rename "spider/js/\350\275\257\351\270\255\347\237\255\345\211\247.js" => "spider/js/\350\275\257\351\270\255\347\237\255\345\211\247[\347\237\255].js" (100%) diff --git "a/spider/js/\344\270\203\347\214\253\347\237\255\345\211\247.js" "b/spider/js/\344\270\203\347\214\253\347\237\255\345\211\247[\347\237\255].js" similarity index 100% rename from "spider/js/\344\270\203\347\214\253\347\237\255\345\211\247.js" rename to "spider/js/\344\270\203\347\214\253\347\237\255\345\211\247[\347\237\255].js" diff --git "a/spider/js/\346\230\237\350\212\275\347\237\255\345\211\247[\347\237\255].js" "b/spider/js/\346\230\237\350\212\275\347\237\255\345\211\247[\347\237\255].js" new file mode 100644 index 00000000..f5aed999 --- /dev/null +++ "b/spider/js/\346\230\237\350\212\275\347\237\255\345\211\247[\347\237\255].js" @@ -0,0 +1,155 @@ +/* +@header({ + searchable: 2, + filterable: 1, + quickSearch: 1, + title: '星芽短剧', + lang: 'ds' +}) +*/ + +// http://localhost:5757/api/星芽短剧?ac=list&t=1&pg=1 +// http://localhost:5757/api/星芽短剧?ac=detail&ids=https://app.whjzjx.cn/v2/theater_parent/detail?theater_parent_id=3523 +// http://localhost:5757/api/星芽短剧?wd=龙王&pg=1 +// http://localhost:5757/api/星芽短剧?play=http://qcapp.xingya.com.cn/h265/wz_mp40905dingtianhou01.mp4?sign=4db245c4e9cd5bd3d3026e2e0f6147a6&t=674ee966&flag=星芽短剧 +var rule = { + 类型: '影视', + title: '星芽短剧', + desc: '星芽短剧纯js版本', + host: 'https://app.whjzjx.cn', + url: '/cloud/v2/theaterfyfilter', + filter_url: '/home_page?theater_class_id=fyclass&type=1&{{fl.type or "class2_ids=0"}}&page_num=fypage&page_size=24', + searchUrl: '/v3/search', + searchable: 2, + quickSearch: 1, + filterable: 1, + filter: 'H4sIAAAAAAAAA6vmUgACJUMlK4VoMBMEquEssGR2aiVQWqmksiBVSQdVKi8xNxUk93zj7qfzutFlyxJzSlNRTMZuA8I4kFlPW1e8bF6BZhbCTJCS5JzE4mKj+MyUYlsDJQx1tZha8dn3snnv0x1NxNpnQrF9T/uXvFjcSqx9phTb97xvw5Pdi1+saHjWTLSthpRb+6xjxvOl84i10IjycH3Z0PZi0VpiLTSnPFxX7n+xrYvoEKXcwqd9bU/7NxGdUCnPGS+2zni6cj/RUWhGeZAunfe0ZzfRFlKeSF+29z6fMp9YC6ngwSlznq5bQKx9xsbUKGxIzvzGVMgbfS1PdxIdkcaUR+SLCT1P180l1kJLyu1rmfhsC9Glm7ERxRY+2bWJhCg0MaTchzMnPGtEr9JxWmiBxT4UkVguVPFYrloA8HqNcnwIAAA=', + headers: { + 'User-Agent': 'okhttp/4.10.0', + 'Accept-Encoding': 'gzip', + 'x-app-id': '7', + 'platform': '1', + 'manufacturer': 'realme', + 'version_name': '3.3.1', + 'user_agent': 'Mozilla/5.0 (Linux; Android 9; RMX1931 Build/PQ3A.190605.05081124; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36', + 'dev_token': 'BFdbZBGOEgG7QDt01ldOQNNfhO2F-rv4QcugZoFZm5_3DlPJEo_bSBeJ6dW2X3eKzxxKKWz3xJCM_u5PppGMqRuYPxcsVg9a-jriWiIoPZvHMSLbcbxTFuasqgTivTY3GabW1yP57LQSsJNQfKoX1BKYGHducrhb0bTwvigfn3gE*', + 'app_version': '3.1.0.1', + 'device_platform': 'android', + 'personalized_recommend_status': '1', + 'device_type': 'RMX1931', + 'device_brand': 'realme', + 'os_version': '9', + 'channel': 'default', + 'raw_channel': 'default', + 'oaid': '', + 'msa_oaid': '', + 'uuid': 'randomUUID_8a0324bf-03c8-4789-8ef8-12d3bcff28f5', + 'device_id': '24250683a3bdb3f118dff25ba4b1cba1a', + 'ab_id': '', + 'support_h265': '1' + }, + timeout: 5000, + class_name: '剧场&热播剧&会员专享&星选好剧&新剧&阳光剧场', + class_url: '1&2&8&7&3&5', + play_parse: true, + class_parse: async () => { + }, + 预处理: async () => { + let html = await post('https://u.shytkjgs.com/user/v1/account/login', { + headers: { + 'User-Agent': 'okhttp/4.10.0', + 'Accept-Encoding': 'gzip', + 'Content-Type': 'application/x-www-form-urlencoded', + 'x-app-id': '7', + 'platform': '1', + 'manufacturer': 'realme', + 'version_name': '3.3.1', + 'user_agent': 'Mozilla/5.0 (Linux; Android 9; RMX1931 Build/PQ3A.190605.05081124; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36', + 'app_version': '3.3.1', + 'device_platform': 'android', + 'personalized_recommend_status': '1', + 'device_type': 'RMX1931', + 'device_brand': 'realme', + 'os_version': '9', + 'channel': 'default', + 'raw_channel': 'default', + 'oaid': '', + 'msa_oaid': '', + 'uuid': 'randomUUID_914e7a9b-deac-4f80-9247-db56669187df', + 'device_id': '24250683a3bdb3f118dff25ba4b1cba1a', + 'ab_id': '', + 'support_h265': '1' + }, + body: "device=24250683a3bdb3f118dff25ba4b1cba1a&install_first_open=false&first_install_time=1723214205125&last_update_time=1723214205125&report_link_url=" + }); + // log('html:', html); + html = JSON.parse(html); + try { + rule.headers['authorization'] = html.data.token + } catch (e) { + rule.headers['authorization'] = html.data.data.token + } + log('authorization:', rule.headers['authorization']); + }, + 推荐: async () => { + return [] + }, + 一级: async function (tid, pg, filter, extend) { + let {input} = this; + let d = []; + let html = await request(input, {headers: rule.headers}); + let data = JSON.parse(html).data.list; + data.forEach(it => { + let id = 'https://app.whjzjx.cn/v2/theater_parent/detail?theater_parent_id=' + it.theater.id; + d.push({ + url: id, + title: it.theater.title, + img: it.theater.cover_url, + desc: it.theater.theme, + }) + }) + return setResult(d); + }, + 二级: async function (ids) { + let {input} = this; + let urls = []; + let html = await request(input, {headers: rule.headers}); + let data = JSON.parse(html).data; + let vod = { + vod_id: input, + vod_name: data.theaters.son_title, + vod_pic: data.cover_url, + } + let playFroms = []; + let playUrls = []; + data.theaters.forEach(it => { + urls.push(it.num + '$' + encodeURIComponent(it.son_video_url)); + }) + playFroms.push('不知道倾情打造'); + vod.vod_play_from = playFroms.join('$$$'); + playUrls.push(urls.join('#')); + vod.vod_play_url = playUrls.join('$$$'); + return vod + }, + 搜索: async function (wd, quick, pg) { + let {input, KEY} = this + let d = []; + let html = await post(input, {headers: rule.headers, body: {"text": KEY}}) + let list = JSON.parse(html).data.theater.search_data; + list.forEach(it => { + let id = 'https://app.whjzjx.cn/v2/theater_parent/detail?theater_parent_id=' + it.id; + d.push({ + url: id, + title: it.title, + desc: it.total, + img: it.cover_url, + content: it.introduction, + }) + }) + return setResult(d); + }, + lazy: async function (flag, id, flags) { + let {input} = this; + return {parse: 0, url: input, js: ''} + }, +}; diff --git "a/spider/js/\347\211\233\347\211\233\347\237\255\345\211\247[\347\237\255].js" "b/spider/js/\347\211\233\347\211\233\347\237\255\345\211\247[\347\237\255].js" new file mode 100644 index 00000000..204129dc --- /dev/null +++ "b/spider/js/\347\211\233\347\211\233\347\237\255\345\211\247[\347\237\255].js" @@ -0,0 +1,229 @@ +/* +@header({ + searchable: 2, + filterable: 1, + quickSearch: 0, + title: '牛牛短句[短]', + '类型': '影视', + lang: 'ds' +}) +*/ + +var rule = { + title: '牛牛短句[短]', + host: 'https://new.tianjinzhitongdaohe.com', + homeUrl: '/api/v1/app/screen/screenType', + searchUrl: '/api/v1/app/search/searchMovie', + url: '/api/v1/app/screen/screenMovie?classify=fyclass&page=fypage', + headers: { + "Cache-Control": "no-cache", + "Content-Type": "application/json;charset=UTF-8", + "User-Agent": "okhttp/4.12.0" + }, + timeout: 5000, + filterable: 1, + limit: 40, + multi: 1, + searchable: 2, + play_parse: true, + search_match: true, + + class_parse: async function () { + const url = `${rule.host}/api/v1/app/screen/screenType`; + try { + const response = await request(url, { + method: 'POST', + headers: rule.headers + }); + const data = JSON.parse(response); + const classes = []; + + if (data.data && data.data[0]?.children?.[0]?.children) { + data.data[0].children[0].children.forEach(vod => { + classes.push({ + type_name: `${vod.name}`, + type_id: vod.name + }); + }); + } + + return { + class: classes, + filters: {} + }; + } catch (e) { + console.error("分类解析错误:", e); + return {class: []}; + } + }, + + 一级: async function () { + const {input, MY_PAGE} = this; + const cid = input.split('classify=')[1].split('&')[0]; + const page = MY_PAGE || 1; + const payload = JSON.stringify({ + condition: { + classify: cid, + typeId: "S1" + }, + pageNum: String(page), + pageSize: rule.limit + }); + + try { + const url = `${rule.host}/api/v1/app/screen/screenMovie`; + const response = await request(url, { + method: 'POST', + headers: rule.headers, + body: payload + }); + const data = JSON.parse(response); + const videos = []; + if (data.data?.records) { + data.data.records.forEach(vod => { + videos.push({ + title: vod.name, + img: vod.cover, + desc: `${vod.totalEpisode}集`, + url: vod.id + }); + }); + } + + return setResult(videos); + } catch (e) { + console.error("一级列表错误:", e); + return []; + } + }, + + 二级: async function () { + const { orId } = this; + let did = orId; + let bofang = ''; + let xianlu = ''; + let content = ''; + + try { + // 获取剧集列表 + const detailPayload = JSON.stringify({ + id: did, + source: 0, + typeId: "S1", + userId: "223664" + }); + + const detailUrl = `${rule.host}/api/v1/app/play/movieDetails`; + const detailResponse = await request(detailUrl, { + method: 'POST', + headers: rule.headers, + body: detailPayload + }); + + const detailData = JSON.parse(detailResponse).data || {}; + if (detailData.episodeList && detailData.episodeList.length > 0) { + const episodes = detailData.episodeList.map(ep => { + return `${ep.episode}$${did}@${ep.id}`; + }); + bofang = episodes.join('#'); + xianlu = '牛牛短句'; + content = detailData.introduce || '暂无剧情介绍'; + } + + return { + vod_name: detailData.name || '未知名称', + vod_pic: detailData.cover || '', + vod_content: content, + vod_play_from: xianlu || '暂无资源', + vod_play_url: bofang || '暂无播放地址$0' + }; + } catch (e) { + console.error("详情解析错误:", e); + return { + vod_name: '加载失败', + vod_pic: '', + vod_content: '详情加载失败,请稍后重试', + vod_play_from: '暂无资源', + vod_play_url: '暂无播放地址$0' + }; + } + }, + + 搜索: async function () { + const {KEY, MY_PAGE} = this; + const page = MY_PAGE || 1; + const payload = JSON.stringify({ + condition: { + typeId: "S1", + value: KEY + }, + pageNum: String(page), + pageSize: rule.limit + }); + + try { + const url = `${rule.host}/api/v1/app/search/searchMovie`; + const response = await request(url, { + method: 'POST', + headers: rule.headers, + body: payload + }); + const data = JSON.parse(response); + const videos = []; + + if (data.data?.records) { + data.data.records.forEach(vod => { + if (rule.search_match && !vod.name.includes(KEY)) return; + + videos.push({ + title: vod.name, + img: vod.cover, + desc: `更新时间${vod.year || '未知'}`, + url: vod.id + }); + }); + } + return setResult(videos); + } catch (e) { + console.error("搜索错误:", e); + return []; + } + }, + + lazy: async function () { + const {input} = this; + const [videoId, episodeId] = input.split('@'); + const payload = JSON.stringify({ + episodeId, + id: videoId, + source: 0, + typeId: "S1", + userId: "223664" + }); + + try { + const url = `${rule.host}/api/v1/app/play/movieDetails`; + const response = await request(url, { + method: 'POST', + headers: rule.headers, + body: payload + }); + const data = JSON.parse(response); + + return { + parse: 0, + url: data.data?.url || '', + header: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36' + } + }; + } catch (e) { + console.error("播放地址获取错误:", e); + return { + parse: 0, + url: '', + header: {} + }; + } + } +}; diff --git "a/spider/js/\350\245\277\351\245\255\347\237\255\345\211\247[\347\237\255].js" "b/spider/js/\350\245\277\351\245\255\347\237\255\345\211\247[\347\237\255].js" new file mode 100644 index 00000000..3a1c8a7b --- /dev/null +++ "b/spider/js/\350\245\277\351\245\255\347\237\255\345\211\247[\347\237\255].js" @@ -0,0 +1,152 @@ +/* +@header({ + searchable: 2, + filterable: 1, + quickSearch: 0, + title: '西饭短剧[短]', + '类型': '影视', + lang: 'ds' +}) +*/ + +var rule = { + title: '西饭短剧[短]', + host: 'https://xifan-api-cn.youlishipin.com', + homeUrl: '/xifan/drama/portalPage?reqType=duanjuCategory&version=2001001&androidVersionCode=28', + searchUrl: '**', + url: '/xifan/drama/portalPage?reqType=aggregationPage&offset=fypage&categoryId=fyclass', + headers: { + 'User-Agent': 'okhttp/3.12.11', + }, + timeout: 5000, + filterable: 1, + limit: 30, + multi: 1, + searchable: 2, + play_parse: true, + search_match: true, + + class_parse: async function () { + let {input} = this; + let html = await request(input); + let classes = []; + let filters = {}; + let data = JSON.parse(html).result.elements[0].contents; + data.forEach((it) => { + const categoryItemVo = it.categoryItemVo || {}; + const typeName = categoryItemVo.oppoCategory; + const typeId = categoryItemVo.categoryId; + const subCategories = categoryItemVo.subCategories || []; + + // 只提取 type 为 duanjuCategory 的作为主分类 + if (it.type && it.type.includes("duanjuCategory")) { + classes.push({ + type_name: typeName, + type_id: `${typeId}@${typeName}`, + }); + } + + // 其他作为筛选条件 + if (subCategories.length > 0) { + filters[typeName] = { + key: categoryItemVo.categoryId, + name: categoryItemVo.oppoCategory, + value: subCategories.map(sub => ({ + n: sub.oppoCategory, + v: `${sub.oppoCategory}@${sub.categoryId}` + })) + }; + } + }); + // 设置筛选条件 + return { + class: classes, + filters: filters + }; + }, + + 一级: async function () { + let {input,MY_PAGE} = this; + const typeId = input.split('categoryId=')[1].split('@')[0]; + const typeName = input.split('categoryId=')[1].split('@')[1]; + let page = (MY_PAGE - 1) * rule.limit; + let current_timestamp = Math.floor(Date.now() / 1000); + let url = `${rule.host}/xifan/drama/portalPage?reqType=aggregationPage&offset=${page}&categoryId=${typeId}&quickEngineVersion=-1&scene=&categoryNames=${encodeURIComponent(typeName)}&categoryVersion=1&density=1.5&pageID=page_theater&version=2001001&androidVersionCode=28&requestId=${current_timestamp}aa498144140ef297&appId=drama&teenMode=false&userBaseMode=false&session=eyJpbmZvIjp7InVpZCI6IiIsInJ0IjoiMTc0MDY1ODI5NCIsInVuIjoiT1BHXzFlZGQ5OTZhNjQ3ZTQ1MjU4Nzc1MTE2YzFkNzViN2QwIiwiZnQiOiIxNzQwNjU4Mjk0In19&feedssession=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dHlwIjowLCJidWlkIjoxNjMzOTY4MTI2MTQ4NjQxNTM2LCJhdWQiOiJkcmFtYSIsInZlciI6MiwicmF0IjoxNzQwNjU4Mjk0LCJ1bm0iOiJPUEdfMWVkZDk5NmE2NDdlNDUyNTg3NzUxMTZjMWQ3NWI3ZDAiLCJpZCI6IjNiMzViZmYzYWE0OTgxNDQxNDBlZjI5N2JkMDY5NGNhIiwiZXhwIjoxNzQxMjYzMDk0LCJkYyI6Imd6cXkifQ.JS3QY6ER0P2cQSxAE_OGKSMIWNAMsYUZ3mJTnEpf-Rc`; + + let d = []; + let html = await request(url, { headers: rule.headers }); + let data = JSON.parse(html).result.elements; + data.forEach((soup) => { + soup.contents.forEach((vod) => { + let dj = vod.duanjuVo; + d.push({ + title: dj.title, + img: dj.coverImageUrl, + desc: dj.total + '集', + url: `${dj.duanjuId}#${dj.source}` + }); + }); + }); + + return setResult(d); + }, + + 二级: async function () { + let {orId} = this; + let [duanjuId, source] = orId.split("#"); + let url = `${rule.host}/xifan/drama/getDuanjuInfo?duanjuId=${duanjuId}&source=${source}&openFrom=homescreen&type=&pageID=page_inner_flow&density=1.5&version=2001001&androidVersionCode=28&requestId=1740658944980aa498144140ef297&appId=drama&teenMode=false&userBaseMode=false&session=eyJpbmZvIjp7InVpZCI6IiIsInJ0IjoiMTc0MDY1ODI5NCIsInVuIjoiT1BHXzFlZGQ5OTZhNjQ3ZTQ1MjU4Nzc1MTE2YzFkNzViN2QwIiwiZnQiOiIxNzQwNjU4Mjk0In19&feedssession=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dHlwIjowLCJidWlkIjoxNjMzOTY4MTI2MTQ4NjQxNTM2LCJhdWQiOiJkcmFtYSIsInZlciI6MiwicmF0IjoxNzQwNjU4Mjk0LCJ1bm0iOiJPUEdfMWVkZDk5NmE2NDdlNDUyNTg3NzUxMTZjMWQ3NWI3ZDAiLCJpZCI6IjNiMzViZmYzYWE0OTgxNDQxNDBlZjI5N2JkMDY5NGNhIiwiZXhwIjoxNzQxMjYzMDk0LCJkYyI6Imd6cXkifQ.JS3QY6ER0P2cQSxAE_OGKSMIWNAMsYUZ3mJTnEpf-Rc`; + + let response = await request(url, { headers: rule.headers }); + let data = JSON.parse(response).result; + VOD = { + vod_name: data.title, + vod_pic: data.coverImageUrl, + vod_content: data.desc || '未知', + vod_remarks: data.updateStatus === 'over' ? `${data.total}集 已完结` : `更新${data.total}集` + }; + + let playUrls = []; + data.episodeList.forEach((ep) => { + playUrls.push(`${ep.index}$${ep.playUrl}`); + }); + + VOD.vod_play_from = '西饭短剧'; + VOD.vod_play_url = playUrls.join("#"); + return VOD; + }, + + 搜索: async function () { + let {input,MY_PAGE,KEY} = this; + let d = []; + let current_timestamp = Math.floor(Date.now() / 1000); + let url = `${rule.host}/xifan/search/getSearchList?keyword=${KEY}84&pageIndex=${MY_PAGE}&version=2001001&androidVersionCode=28&requestId=${current_timestamp}ea3a14bc0317d76f&appId=drama&teenMode=false&userBaseMode=false&session=eyJpbmZvIjp7InVpZCI6IiIsInJ0IjoiMTc0MDY2ODk4NiIsInVuIjoiT1BHX2U5ODQ4NTgzZmM4ZjQzZTJhZjc5ZTcxNjRmZTE5Y2JjIiwiZnQiOiIxNzQwNjY4OTg2In19&feedssession=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dHlwIjowLCJidWlkIjoxNjM0MDU3ODE4OTgxNDk5OTA0LCJhdWQiOiJkcmFtYSIsInZlciI6MiwicmF0IjoxNzQwNjY4OTg2LCJ1bm0iOiJPUEdfZTk4NDg1ODNmYzhmNDNlMmFmNzllNzE2NGZlMTljYmMiLCJpZCI6ImVhZGE1NmEyZWEzYTE0YmMwMzE3ZDc2ZmVjODJjNzc3IiwiZXhwIjoxNzQxMjczNzg2LCJkYyI6ImJqaHQifQ.IwuI0gK077RF4G10JRxgxx4GCG502vR8Z0W9EV4kd-c`; + + let html = await request(url, {headers: rule.headers }); + let data = JSON.parse(html).result.elements; + data.forEach((soup) => { + soup.contents.forEach((vod) => { + let dj = vod.duanjuVo; + let name = dj.title.replace(/<\/?tag>/g, ""); + if (rule.search_match && !new RegExp(KEY, "i").test(name)) { + return; + } + + d.push({ + title: name, + img: dj.coverImageUrl, + desc: dj.total + '集', + url: `${dj.duanjuId}#${dj.source}` + }); + }); + }); + + return setResult(d); + }, + lazy: async function () { + let {input} = this; + return { + parse: 0, + url: input + }; + }, +} diff --git "a/spider/js/\350\275\257\351\270\255\347\237\255\345\211\247.js" "b/spider/js/\350\275\257\351\270\255\347\237\255\345\211\247[\347\237\255].js" similarity index 100% rename from "spider/js/\350\275\257\351\270\255\347\237\255\345\211\247.js" rename to "spider/js/\350\275\257\351\270\255\347\237\255\345\211\247[\347\237\255].js" From 752b4a0c34efe900ba184aa25067398c4fd48833 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Sat, 17 Jan 2026 19:26:52 +0800 Subject: [PATCH 042/101] Update files and clean up spider js scripts --- public/sub/order_common.example.html | 2 + ...57\345\217\257\345\275\261\350\247\206.js" | 60 --------- ...57\350\247\206\345\275\261\351\231\242.js" | 121 ------------------ ...37\350\276\260\345\275\261\351\231\242.js" | 34 ++--- 4 files changed, 16 insertions(+), 201 deletions(-) delete mode 100644 "spider/js/\345\217\257\345\217\257\345\275\261\350\247\206.js" delete mode 100644 "spider/js/\345\217\257\350\247\206\345\275\261\351\231\242.js" rename "spider/js/\345\245\275\344\271\220\345\275\261\350\247\206.js" => "spider/js/\346\230\237\350\276\260\345\275\261\351\231\242.js" (87%) diff --git a/public/sub/order_common.example.html b/public/sub/order_common.example.html index a82a7930..99d5a641 100644 --- a/public/sub/order_common.example.html +++ b/public/sub/order_common.example.html @@ -1,7 +1,9 @@ +豆瓣 设置中心 番茄小说 腾云驾雾 央视大全 +短剧聚合 IPTV [优] [盘] diff --git "a/spider/js/\345\217\257\345\217\257\345\275\261\350\247\206.js" "b/spider/js/\345\217\257\345\217\257\345\275\261\350\247\206.js" deleted file mode 100644 index f1d6224c..00000000 --- "a/spider/js/\345\217\257\345\217\257\345\275\261\350\247\206.js" +++ /dev/null @@ -1,60 +0,0 @@ -/* -@header({ - searchable: 0, - filterable: 0, - quickSearch: 0, - title: '可可影视', - '类型': '影视', - lang: 'ds' -}) -*/ - -var rule = { - 类型: '影视', - title: '可可影视', - host: 'https://www.keke1.app/', - url: '/show/fyclass-----2-fypage.html', - filter_url: '', - searchUrl: '/search?k=**穹&page=fypage', - searchable: 0, - quickSearch: 0, - filterable: 0, - filter: '', - headers: { - 'User-Agent': MOBILE_UA, - }, - timeout: 5000, - class_name: '电影&连续剧&动漫&综艺&短剧', - class_url: '1&2&3&4&6', - play_parse: true, - class_parse: async () => { - }, - 预处理: async () => { - }, - 图片替换: async function (input) { - let {HOST} = this; - // console.log('HOST:', HOST); - return input.replace(HOST, "https://vres.cfaqcgj.com"); - }, - 推荐: '.section-box:eq(2)&&.module-box-inner&&.module-item;*;*;*;*', - double: false, - 一级: '.module-box-inner&&.module-item;.v-item-title:eq(1)&&Text;img:last-of-type&&data-original;.v-item-bottom&&span&&Text;a&&href', - 二级: { - title: '.detail-pic&&img&&alt;.detail-tags&&a&&Text', - img: '.detail-pic&&img&&data-original', - desc: '.detail-info-row-main:eq(-2)&&Text;.detail-tags&&a&&Text;.detail-tags&&a:eq(1)&&Text;.detail-info-row-main:eq(1)&&Text;.detail-info-row-main&&Text', - content: '.detail-desc&&Text', - tabs: '.source-item-label', - //tabs: 'body&&.source-item-label[id]', - lists: '.episode-list:eq(#id) a', - }, - 搜索: '.search-result-list&&a;.title:eq(1)&&Text;*;.search-result-item-header&&Text;a&&href;.desc&&Text', - lazy: $js.toString(async () => { - log('input:', input); - return { - parse: 1, - url: input, - js: 'document.querySelector("#my-video video").click()', - } - }), -}; \ No newline at end of file diff --git "a/spider/js/\345\217\257\350\247\206\345\275\261\351\231\242.js" "b/spider/js/\345\217\257\350\247\206\345\275\261\351\231\242.js" deleted file mode 100644 index 5847df78..00000000 --- "a/spider/js/\345\217\257\350\247\206\345\275\261\351\231\242.js" +++ /dev/null @@ -1,121 +0,0 @@ -/* -@header({ - searchable: 2, - filterable: 1, - quickSearch: 1, - title: '可视影视', - '类型': '影视', - lang: 'ds' -}) -*/ - -var rule = { - 类型:'影视', - title:'可视影视', - desc:'251207_DS', - host:'https://www.ketv.cc', - url: '/s/fyfilter.html', - searchUrl:'/search/**----------fypage---.html', - searchable:2,quickSearch:1,timeout:5000,play_parse:true,filterable:1, - headers: {'User-Agent': 'MOBILE_UA'}, - class_name: '电影&电视剧&综艺&动漫&短剧&动画片', - class_url: 'movie&series&variety&anime&skit&animation', - filter_url: '{{fl.cateId or "fyclass"}}-{{fl.area}}-{{fl.by}}-{{fl.class}}-{{fl.lang}}-{{fl.letter}}---fypage---{{fl.year}}', - - 预处理: async () => { - return [] - }, - - 推荐: async function (tid, pg, filter, extend) { - return this.一级(tid, pg, filter, extend); - }, - - 一级: async function (tid, pg, filter, extend) { - let {input, pdfa, pdfh, pd} = this; - let html = await request(input); - let d = []; - let data = pdfa(html, '.lazyload'); - data.forEach((it) => { - d.push({ - title: pdfh(it, 'a&&title'), - pic_url: pd(it, '.lazyload&&data-original'), - desc: pdfh(it, '.text_right&&Text'), - url: pd(it, 'a&&href'), - }) - }); - return setResult(d) - }, - - 二级: async function (ids) { - let {input, pdfa, pdfh, pd} = this; - let html = await request(input); - let VOD = {}; - VOD.vod_id = input; - VOD.vod_name = pdfh(html, 'h2.title&&Text'); - VOD.type_name = pdfh(html, '.data:contains(类型)&&Text').replace('类型:', ''); - VOD.vod_pic = pd(html, '#detail_rating img&&src', input); - VOD.vod_remarks = pdfh(html, '.data_style&&Text'); - VOD.vod_content = pdfh(html, '.content_desc span&&Text'); - VOD.vod_year = pdfh(html, '.data:contains(年份) a&&Text'); - VOD.vod_area = pdfh(html, '.data:contains(地区) a&&Text'); - VOD.vod_director = pdfh(html, '.data:contains(导演)&&Text').replace('导演:', '').trim(); - VOD.vod_actor = pdfh(html, '.data:contains(主演)&&Text').replace('主演:', '').trim(); - let r_ktabs = pdfa(html,'#NumTab a'); - let ktabs = r_ktabs.map(it => { - let altText = pd(it, 'a&&alt'); - return altText || pdfh(it, 'Text').replace(/^\s*[\uE000-\uF8FF]+\s*/, '').trim(); - }).filter(name => name && !name.includes('Playlist')); - VOD.vod_play_from = ktabs.join('$$$'); - let klists = []; - let r_plists = pdfa(html, '.play_list_box .content_playlist.clearfix'); - r_plists.forEach((rp, index) => { - if (index < ktabs.length) { - let klist = pdfa(rp, 'a').map((it) => { - return pdfh(it, 'a&&Text') + '$' + pd(it, 'a&&href', input); - }).filter(item => { - return !item.includes('APP播放'); - }); - klist = klist.join('#'); - klists.push(klist); - } - }); - VOD.vod_play_url = klists.join('$$$'); - return VOD; - }, - - 搜索: async function (wd, quick, pg) { - return this.一级(wd, quick, pg); - }, - - lazy: async function lazyFunc() { - let html = await request(input); - let kcode = JSON.parse(html.split('aaaa=')[1].split('<')[0]); - let kurl = kcode.url; - if (/\.(m3u8|mp4)/.test(kurl)) { - input = { - jx: 0, - parse: 0, - url: kurl, - header: { - 'User-Agent': MOBILE_UA, - 'Referer': getHome(kurl) - } - }; - } else { - input = { - jx: 0, - parse: 1, - url: input - }; - } -}, -filter_def:{movie:{cateId:'movie'},series:{cateId:'series'},variety:{cateId:'variety'},anime:{cateId:'anime'},skit:{cateId:'skit'},animation:{cateId:'animation'}}, -filter:{ -"movie":[{"key":"cateId","name":"分类","value":[{"n":"全部","v":"all"},{"n":"动作片","v":"Action"},{"n":"喜剧片","v":"Funny"},{"n":"爱情片","v":"Lovestory"},{"n":"科幻片","v":"Science"},{"n":"恐怖片","v":"terrorist"},{"n":"剧情片","v":"plot"},{"n":"战争片","v":"war"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"大陆","v":"大陆"},{"n":"香港","v":"香港"},{"n":"台湾","v":"台湾"},{"n":"美国","v":"美国"},{"n":"法国","v":"法国"},{"n":"英国","v":"英国"},{"n":"日本","v":"日本"},{"n":"韩国","v":"韩国"},{"n":"德国","v":"德国"},{"n":"泰国","v":"泰国"},{"n":"印度","v":"印度"},{"n":"意大利","v":"意大利"},{"n":"西班牙","v":"西班牙"},{"n":"加拿大","v":"加拿大"},{"n":"其他","v":"其他"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]},{"key":"by","name":"排序","value":[{"n":"按最新","v":"time"},{"n":"按最热","v":"hits"},{"n":"按评分","v":"score"}]}], -"series":[{"key":"cateId","name":"分类","value":[{"n":"全部","v":"all"},{"n":"国产剧","v":"china"},{"n":"香港剧","v":"hongkong"},{"n":"韩国剧","v":"korea"},{"n":"欧美剧","v":"eus"},{"n":"日本剧","v":"japan"},{"n":"台湾剧","v":"taiwan"},{"n":"海外剧","v":"overseas"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"大陆","v":"大陆"},{"n":"香港","v":"香港"},{"n":"台湾","v":"台湾"},{"n":"美国","v":"美国"},{"n":"法国","v":"法国"},{"n":"英国","v":"英国"},{"n":"日本","v":"日本"},{"n":"韩国","v":"韩国"},{"n":"德国","v":"德国"},{"n":"泰国","v":"泰国"},{"n":"印度","v":"印度"},{"n":"意大利","v":"意大利"},{"n":"西班牙","v":"西班牙"},{"n":"加拿大","v":"加拿大"},{"n":"其他","v":"其他"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]},{"key":"by","name":"排序","value":[{"n":"按最新","v":"time"},{"n":"按最热","v":"hits"},{"n":"按评分","v":"score"}]}], -"variety":[{"key":"cateId","name":"分类","value":[{"n":"全部","v":"all"},{"n":"大陆","v":"cn"},{"n":"日韩","v":"JapanKorea"},{"n":"港台","v":"HongKongTaiwan"},{"n":"欧美","v":"Eusa"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"大陆","v":"大陆"},{"n":"香港","v":"香港"},{"n":"台湾","v":"台湾"},{"n":"美国","v":"美国"},{"n":"法国","v":"法国"},{"n":"英国","v":"英国"},{"n":"日本","v":"日本"},{"n":"韩国","v":"韩国"},{"n":"德国","v":"德国"},{"n":"泰国","v":"泰国"},{"n":"印度","v":"印度"},{"n":"意大利","v":"意大利"},{"n":"西班牙","v":"西班牙"},{"n":"加拿大","v":"加拿大"},{"n":"其他","v":"其他"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]},{"key":"by","name":"排序","value":[{"n":"按最新","v":"time"},{"n":"按最热","v":"hits"},{"n":"按评分","v":"score"}]}], -"anime":[{"key":"cateId","name":"分类","value":[{"n":"全部","v":"all"},{"n":"国产","v":"chn"},{"n":"日本","v":"jp"},{"n":"欧美","v":"usa"},{"n":"海外","v":"others"}]},{"key":"area","name":"地区","value":[{"n":"全部","v":""},{"n":"大陆","v":"大陆"},{"n":"香港","v":"香港"},{"n":"台湾","v":"台湾"},{"n":"美国","v":"美国"},{"n":"法国","v":"法国"},{"n":"英国","v":"英国"},{"n":"日本","v":"日本"},{"n":"韩国","v":"韩国"},{"n":"德国","v":"德国"},{"n":"泰国","v":"泰国"},{"n":"印度","v":"印度"},{"n":"意大利","v":"意大利"},{"n":"西班牙","v":"西班牙"},{"n":"加拿大","v":"加拿大"},{"n":"其他","v":"其他"}]},{"key":"year","name":"年份","value":[{"n":"全部","v":""},{"n":"2024","v":"2024"},{"n":"2023","v":"2023"},{"n":"2022","v":"2022"},{"n":"2021","v":"2021"},{"n":"2020","v":"2020"},{"n":"2019","v":"2019"},{"n":"2018","v":"2018"},{"n":"2017","v":"2017"},{"n":"2016","v":"2016"},{"n":"2015","v":"2015"},{"n":"2014","v":"2014"},{"n":"2013","v":"2013"},{"n":"2012","v":"2012"},{"n":"2011","v":"2011"},{"n":"2010","v":"2010"},{"n":"2009","v":"2009"},{"n":"2008","v":"2008"}]},{"key":"letter","name":"字母","value":[{"n":"全部","v":""},{"n":"A","v":"A"},{"n":"B","v":"B"},{"n":"C","v":"C"},{"n":"D","v":"D"},{"n":"E","v":"E"},{"n":"F","v":"F"},{"n":"G","v":"G"},{"n":"H","v":"H"},{"n":"I","v":"I"},{"n":"J","v":"J"},{"n":"K","v":"K"},{"n":"L","v":"L"},{"n":"M","v":"M"},{"n":"N","v":"N"},{"n":"O","v":"O"},{"n":"P","v":"P"},{"n":"Q","v":"Q"},{"n":"R","v":"R"},{"n":"S","v":"S"},{"n":"T","v":"T"},{"n":"U","v":"U"},{"n":"V","v":"V"},{"n":"W","v":"W"},{"n":"X","v":"X"},{"n":"Y","v":"Y"},{"n":"Z","v":"Z"},{"n":"0-9","v":"0-9"}]},{"key":"by","name":"排序","value":[{"n":"按最新","v":"time"},{"n":"按最热","v":"hits"},{"n":"按评分","v":"score"}]}], -"skit":[{"key":"by","name":"排序","value":[{"n":"按最新","v":"time"},{"n":"按最热","v":"hits"},{"n":"按评分","v":"score"}]}], -"animation":[{"key":"area","name":"地区","value":[{"n":"全部","v":"all"},{"n":"大陆动画片","v":"大陆"},{"n":"日本动画片","v":"日本"},{"n":"美国动画片","v":"美国"},{"n":"韩国动画片","v":"韩国"},{"n":"香港动画片","v":"香港"}]},{"key":"by","name":"排序","value":[{"n":"按最新","v":"time"},{"n":"按最热","v":"hits"},{"n":"按评分","v":"score"}]}] -} -} \ No newline at end of file diff --git "a/spider/js/\345\245\275\344\271\220\345\275\261\350\247\206.js" "b/spider/js/\346\230\237\350\276\260\345\275\261\351\231\242.js" similarity index 87% rename from "spider/js/\345\245\275\344\271\220\345\275\261\350\247\206.js" rename to "spider/js/\346\230\237\350\276\260\345\275\261\351\231\242.js" index 243cc497..a95204f1 100644 --- "a/spider/js/\345\245\275\344\271\220\345\275\261\350\247\206.js" +++ "b/spider/js/\346\230\237\350\276\260\345\275\261\351\231\242.js" @@ -3,17 +3,18 @@ searchable: 1, filterable: 1, quickSearch: 0, - title: '好乐影视', + title: '星辰影院', + '类型': '影视', lang: 'ds' }) */ var rule = { 类型: '影视', - title: '好乐影视', - host: 'https://www.haolev.com', - url: '/haoshow/fyfilter', - searchUrl: '/lesearch/**----------fypage---.html', + title: '星辰影院', + host: 'https://www.xcyycn.com', + url: '/vs/fyfilter', + searchUrl: '/s.html?wd=**&submit=', headers: {'User-Agent': 'MOBILE_UA'}, searchable: 1, quickSearch: 0, filterable: 1, play_parse: true, double: false, limit: 6, filter_url: '{{fl.cateId}}-{{fl.area}}-{{fl.by}}-{{fl.class}}-----fypage---{{fl.year}}.html', @@ -24,22 +25,15 @@ var rule = { class_url: '1&2&4&3', filter: 'H4sIAAAAAAAAA+2Zy04bSRSG9/MYXrOohtwmrzLKwhNZSpRMRoJMJBQhQcDEBgcbROw4OEDENYRLcxkwDbZfxlVtv8WUXVXnnJ4hx42HRRbe+T+nbn91ddXX5bcJL/H4t7eJF6nxxOPE05fJsbHEUOJV8o+UljK7o6bTWr9Jvvwr1S33qhNO77andzthLRITQzY6t9usVWzUCsgVK7otlzPC5cKdRXl5ZXNWuJyaKqjJos1ZAfUyx3ZwKKA/GDgKaDPzqRlkXZtGuFzr0Je1jzZnBfEXLl+hv46ANqfn1LvPrk0jYJxzR2Ftz43TCKj3bj8sLrp6RkB/s0vt8jfXnxGQ23qPc2YF5A7PZXDgckZAbmFW5k9czgiXa16va8c2ZwXUy2+2NmA+jXC59tpp87Jgc1ZAvUJOTcJzNwLmulHQs+jm2giYl4PtZn3dzYsRMJ9rB2H2vZtPI7BerpVZhXpdAf1tNXDVWgHjnGmE37fcOI2A/qbq7c91158RuJbyauUE1lJXQL3KWjMIwp1JVxU0zNyXJfXJ9WrFxJNO1ryNydFUkryMFV/mgrgv4+ZOuzzrDBkB3W6XVfXIdWsEPmhfXdbhQXcFGKovyJWac2METERpS1X23UQYgQvkG9azAh7K/DHmrIA2Tz9izgoYZ/0Cc1ZAvZm8diwz7t1BTZZCmNcLp4yrwWp4GRozYa2kim6aUON2sK7mG7ph2BGchhIffBlsu7QR6M2n3vyIt/S5PJx29YyAekVfdyS/fHVVQYO3/Imsz8tD9xBRQxv1UzMfzQC2LBqCcVTWWpOnegBuKKBhRSyuynTVrQgjoPbFmZ5WV9UIGOOHC5l2W40V0VmT/rWugAP8dxS85Pbk7pRzYQTkygFZBEaQw0P6yzgI1LgdzqlKCbbDroDxL5X1JujGbwR9ccdTyVHy4l6eNa9qMV/cYTF8z8a6P0l8BOMjND6M8WEa9zDu0bjAuCBx71eI658k/gjjj2j8IcYf0vgDjD+g8fsYv0/j6Nejfj3061G/Hvr1qF8P/XrUr4d+PepXoF9B/Qr0K6hfgX4F9SvQr6B+BfoV1K9Av4L6FehXUL8C/QrqV6BfQf0K9Kt/0mX5+zguSrWwJIP8fxalymVV6bxdOrNtvH6uS+PLltUnmPKXbfLZ89djNNk6mpEZd+iMPf1zNNXp/snQL4nhHzNmeHwlV+fjHmsrtWYAO64RMID9HX0oudfdiDhHHnc8ccchd+Spvy/kJnCrEbG2foZbWd5l+JpjTI5NOeZjWZ9hU46T++VW9vuBYX2OTTn+5Lic/V4J9vDbwoo47M3xLsfQLJczvNsvQ9/IyQOa/b/E15tVe5MoS9IcpfakzRiczHDg3ZFob+bnvhh6MzNLurci1t7keWumHZDngDwH5Hkzed67U/LU56u6/h7hTxsiR0fnUKDlIqEorUbL0RCUqx7pgytajoaixBktR0OE3H54i8lRJEem7G0kd4vJUCRHdSwJM2TDESZ7q8gQNEdgHEFzhMmRG3ubzNA1R8IctXLkrQqr4T7MixFxKDKcPmh9hWtRI35iUuyXBjnC7PvekyHF3hzYm9Z602YM0mKIkr23ZQh5wD0D7hlwzy24Z+SuuKe7h4ZX161sENlWbSjKKZFykVCUj6LlaCjKR9FyNASbbM9/2cxVCzncQcOmN3Ms8xvYBuo4JzJ70q1U5QZ86RkRh7ZYwmFOZJZGOBJj6K512Gj5GdemEfg006pahefYFXGoqV8S4+7s2DtJ7r6L++++vtDeWMMjvCN+YlLhaISjmH5Jhf2nkqOYGDdWDAvcwa1UjFu1u7i36u/OacA1A64ZcM0NXDPxDyQRoaiuJgAA', lazy: async function () { - let {input, pdfa, pdfh, pd} = this - const html = JSON.parse((await req(input)).content.match(/r player_.*?=(.*?) Date: Sat, 17 Jan 2026 19:51:14 +0800 Subject: [PATCH 043/101] =?UTF-8?q?Add=20=E7=B1=B3=E5=85=94=E9=9F=B3?= =?UTF-8?q?=E4=B9=90[=E5=90=AC].js=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\351\237\263\344\271\220[\345\220\254].js" | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 "spider/js/\347\261\263\345\205\224\351\237\263\344\271\220[\345\220\254].js" diff --git "a/spider/js/\347\261\263\345\205\224\351\237\263\344\271\220[\345\220\254].js" "b/spider/js/\347\261\263\345\205\224\351\237\263\344\271\220[\345\220\254].js" new file mode 100644 index 00000000..6a2a6720 --- /dev/null +++ "b/spider/js/\347\261\263\345\205\224\351\237\263\344\271\220[\345\220\254].js" @@ -0,0 +1,59 @@ +/* +@header({ + searchable: 2, + filterable: 0, + quickSearch: 0, + title: '米兔音乐', + '类型': '影视', + lang: 'ds' +}) +*/ + +var rule = { + title: '米兔音乐', + host: 'https://api.qqmp3.vip', + url: '/api/fyclass', + searchUrl: '/api/songs.php?type=search&keyword=**', + class_name: '热门歌曲&新歌曲&随机歌曲', + class_url: 'songs.php&songs.php?type=new&songs.php?type=rand', + searchable: 2, + quickSearch: 0, + filterable: 0, + play_parse: true, + limit: 6, + double: true, + headers: { + 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; V2284A Build/V417IR; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.61 Safari/537.36', + 'Accept': '*/*', + 'Origin': 'https://www.qqmp3.vip', + 'referer': 'https://www.qqmp3.vip', + 'x-requested-with': 'com.mmbox.xbrowser', + 'Sec-Fetch-Site': 'same-site', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Dest': 'empty', + 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7' + }, + 推荐: '*', + 一级: 'json:data;name;pic;artist;rid', + 二级: '*', + 搜索: 'json:data;name;pic;artist;rid', + lazy: async function() { + let ridMatch = this.input.match(/api\/([^/?]+)/); + if (!ridMatch) return this.input; + let rid = ridMatch[1]; + let api = 'https://api.qqmp3.vip/api/kw.php?rid=' + rid; + // console.log('解析接口:', api); + let json = await request(api); + let data = JSON.parse(json); + if (data.code === 200 && data.data?.url) { + return { + parse: 0, + url: data.data.url, + header: this.headers, + lrc: data.data.lrc || '', + playMode: 'repeat' + }; + } + return this.input; + }, +}; \ No newline at end of file From 36d010af9563a894cd094a830afd4d358d8b4dad Mon Sep 17 00:00:00 2001 From: Taois Date: Sat, 17 Jan 2026 22:54:16 +0800 Subject: [PATCH 044/101] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=92=8C=E5=81=9C=E6=AD=A2=E7=9A=84=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.js | 4 +++- public/index.html | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 6b140a7a..2c27bfac 100644 --- a/index.js +++ b/index.js @@ -250,7 +250,7 @@ const start = async () => { } else { console.log('Not running on Vercel!'); } - + return true; } catch (err) { fastify.log.error(err); process.exit(1); @@ -265,8 +265,10 @@ const stop = async () => { // 停止主服务器 await fastify.server.close(); console.log('🛑 所有服务已优雅停止'); + return true; } catch (err) { fastify.log.error(`停止服务器时发生错误:${err.message}`); + return false; } }; diff --git a/public/index.html b/public/index.html index 796ff944..4b19495f 100644 --- a/public/index.html +++ b/public/index.html @@ -161,6 +161,7 @@

    友链(白嫖接口服务)

  • 源动力-老
  • 电竞专业反应测试
  • 桌面启动器
  • +
  • 不知名获取网盘CK工具

AI接入

    From 0edd3fe18e027d539555a879136d32b6fa0ac335 Mon Sep 17 00:00:00 2001 From: Taois Date: Sun, 18 Jan 2026 01:52:40 +0800 Subject: [PATCH 045/101] =?UTF-8?q?feat:=20=E7=A1=AE=E4=BF=9D=E5=B0=8F?= =?UTF-8?q?=E8=AF=B4=E6=BA=90=E9=83=BD=E6=9C=89=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...0\203\347\214\253\345\260\217\350\257\264[\344\271\246].js" | 3 +++ ...5\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" | 3 +++ ...0\203\347\214\253\345\260\217\350\257\264[\344\271\246].py" | 1 + 3 files changed, 7 insertions(+) diff --git "a/spider/js/\344\270\203\347\214\253\345\260\217\350\257\264[\344\271\246].js" "b/spider/js/\344\270\203\347\214\253\345\260\217\350\257\264[\344\271\246].js" index 45a2079e..6bc4e80b 100644 --- "a/spider/js/\344\270\203\347\214\253\345\260\217\350\257\264[\344\271\246].js" +++ "b/spider/js/\344\270\203\347\214\253\345\260\217\350\257\264[\344\271\246].js" @@ -5,11 +5,14 @@ quickSearch: 0, title: '七猫小说[书]', logo: 'https://cdn-front.qimao.com/global/static/images/favicon2022.ico', + author: '道长', + '类型': '小说', lang: 'ds' }) */ var rule = { + author: '道长', 类型: '小说', //影视|听书|漫画|小说 title: '七猫小说[书]', host: 'https://www.qimao.com/', diff --git "a/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" "b/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" index 12279717..7a5a2929 100644 --- "a/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" +++ "b/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" @@ -4,6 +4,8 @@ filterable: 1, quickSearch: 0, title: '番茄小说[书]', + author: '道长', + '类型': '小说', lang: 'ds' }) */ @@ -29,6 +31,7 @@ const fqweb_host = 'https://qkfqapi.vv9v.cn'; // const fqweb_host = 'http://8.148.83.169:22222/docs'; //备选 var rule = { + author: '道长', 类型: '小说', title: '番茄小说[书]', desc: '番茄小说纯js版本', diff --git "a/spider/py/\344\270\203\347\214\253\345\260\217\350\257\264[\344\271\246].py" "b/spider/py/\344\270\203\347\214\253\345\260\217\350\257\264[\344\271\246].py" index 1b0bde65..3da53506 100644 --- "a/spider/py/\344\270\203\347\214\253\345\260\217\350\257\264[\344\271\246].py" +++ "b/spider/py/\344\270\203\347\214\253\345\260\217\350\257\264[\344\271\246].py" @@ -4,6 +4,7 @@ filterable: 1, quickSearch: 1, title: '七猫小说', + 类型: '小说', logo: 'https://cdn-front.qimao.com/global/static/images/favicon2022.ico', lang: 'hipy' }) From be0d97d2b34f932e6246c0655c014f04b9428f9f Mon Sep 17 00:00:00 2001 From: Taois Date: Sun, 18 Jan 2026 01:59:36 +0800 Subject: [PATCH 046/101] =?UTF-8?q?feat:=20=E5=8F=91=E5=B8=83=E6=96=B0?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ docs/updateRecord.md | 11 +++++++++++ package.json | 2 +- public/index.html | 2 ++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d911457e..3cbdcc29 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,10 @@ nodejs作为服务端的drpy实现。全面升级异步写法 ## 更新记录 +### 20260118 + +更新至V1.3.18 + ### 20260115 更新至V1.3.17 diff --git a/docs/updateRecord.md b/docs/updateRecord.md index 8fe8d811..4a487152 100644 --- a/docs/updateRecord.md +++ b/docs/updateRecord.md @@ -1,5 +1,16 @@ # drpyS更新记录 +### 20260118 + +更新至V1.3.18 + +1. 合并E佬修改的源,新增&修复源 +2. 新增drpy2-fast壳依赖,需自行适配爱老so文件,取消不可用的dr2的t4模式,改为使用drpy2-fast本地依赖 +3. 规范一些小说源的代码,确保统一返回了类型:'小说' +4. 修改了index.js中的start、stop函数确保有返回值,适配新版zy本地插件 +5. 调整了部分内置解析 + 其它细节自测... + ### 20260115 更新至V1.3.17 diff --git a/package.json b/package.json index 25b196bc..e350953d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "drpy-node", - "version": "1.3.17", + "version": "1.3.18", "main": "index.js", "type": "module", "scripts": { diff --git a/public/index.html b/public/index.html index 4b19495f..83d6552e 100644 --- a/public/index.html +++ b/public/index.html @@ -67,6 +67,8 @@

    免费壳子推荐

  • 皮卡丘

更新记录

+

20260118

+

更新至V1.3.18

20260115

更新至V1.3.17

20260113

From fe27ceafd6957a63598948cd967a55d6e3b9163a Mon Sep 17 00:00:00 2001 From: Taois Date: Sun, 18 Jan 2026 17:28:42 +0800 Subject: [PATCH 047/101] =?UTF-8?q?feat:=20=E5=B0=9D=E8=AF=95=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=BA=95=E5=B1=82=E6=8B=A6=E6=88=AA=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E5=A4=B4=E7=9A=84ua=E6=89=8B=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs_drpy/fetchAxios.js | 58 +++++++++++++++++++++++++- spider/js/_debug.js | 85 +++++++++++++++++++++++++++++++++++++++ spider/js/_lib.request.js | 28 +++++++++++-- utils/createAxiosAgent.js | 21 ++++++++-- 4 files changed, 184 insertions(+), 8 deletions(-) create mode 100644 spider/js/_debug.js diff --git a/libs_drpy/fetchAxios.js b/libs_drpy/fetchAxios.js index 789fe5c2..4e90ffa8 100644 --- a/libs_drpy/fetchAxios.js +++ b/libs_drpy/fetchAxios.js @@ -4,6 +4,50 @@ */ import FormData from 'form-data'; import https from "https"; +import diagnosticsChannel from 'diagnostics_channel'; + +let undiciStripUASubscribed = false; + +function ensureUndiciStripUASubscription() { + if (undiciStripUASubscribed) { + return; + } + undiciStripUASubscribed = true; + + diagnosticsChannel.channel('undici:request:create').subscribe(({request}) => { + if (!request || !Array.isArray(request.headers)) { + return; + } + const headers = request.headers; + + let shouldStrip = false; + for (let i = 0; i < headers.length; i += 2) { + const k = headers[i]; + if (typeof k === 'string' && k.toLowerCase() === 'x-remove-user-agent') { + shouldStrip = true; + break; + } + } + if (!shouldStrip) { + return; + } + + for (let i = 0; i < headers.length; i += 2) { + const k = headers[i]; + if (typeof k === 'string' && k.toLowerCase() === 'x-remove-user-agent') { + headers.splice(i, 2); + i -= 2; + } + } + for (let i = 0; i < headers.length; i += 2) { + const k = headers[i]; + if (typeof k === 'string' && k.toLowerCase() === 'user-agent') { + headers.splice(i, 2); + i -= 2; + } + } + }); +} /** * FetchAxios类 - HTTP客户端实现 @@ -71,6 +115,18 @@ class FetchAxios { finalConfig = await interceptor(finalConfig) || finalConfig; } + if (finalConfig.headers) { + const headerKeys = Object.keys(finalConfig.headers); + for (const key of headerKeys) { + if (key.toLowerCase() === 'user-agent' && finalConfig.headers[key] === 'RemoveUserAgent') { + delete finalConfig.headers[key]; + finalConfig.headers['x-remove-user-agent'] = '1'; + ensureUndiciStripUASubscription(); + break; + } + } + } + // 拼接查询参数 if (finalConfig.params) { const query = new URLSearchParams(finalConfig.params).toString(); @@ -300,4 +356,4 @@ export function createHttpsInstance() { responseType: 'arraybuffer', httpsAgent: httpsAgent }); -} \ No newline at end of file +} diff --git a/spider/js/_debug.js b/spider/js/_debug.js new file mode 100644 index 00000000..d32b3df1 --- /dev/null +++ b/spider/js/_debug.js @@ -0,0 +1,85 @@ +// _debug.js +// 测试方法: http://localhost:5757/api/_debug?pwd=dzyyds +var rule = { + title: '_debug', + description: '这是描述', + 类型: '测试', + searchUrl: '', + class_parse: async () => { + log(`[${rule.title}] --class_parse--`); + return [ + {type_id: '1', type_name: '电影'}, + {type_id: '2', type_name: '电视剧'}, + {type_id: '3', type_name: '综艺'}, + {type_id: '4', type_name: '动漫'}, + ] + }, + 预处理: async () => { + log(`[${rule.title}] --预处理--`); + rule.title = '_debug'; + }, + 推荐: async () => { + // return '这是推荐:' + rule.title; + let d = []; + let html = '{}'; + html = await request('https://httpbin.org/headers', { + headers: { + 'Accept': '*/*', + 'User-Agent': '' + } + }); + // log(html); + d.push({ + title: 'request结果1-传空UA', + content: html.parseX.headers, + }); + + html = await request('https://httpbin.org/headers', { + headers: { + 'Accept': '*/*', + 'User-Agent': 'RemoveUserAgent', + } + }); + // log(html); + d.push({ + title: 'request结果2-不传UA', + content: html.parseX.headers, + }); + + html = (await req('https://httpbin.org/headers', { + headers: { + 'Accept': '*/*', + 'User-Agent': 'RemoveUserAgent', + } + })).content; + d.push({ + title: 'req结果-不传UA', + content: html.parseX.headers, + }); + + html = (await req('https://conn.origjoy.com/auth/init?appid=d4eeacc6cec3434fbc8c41608a3056a0&mac=0afa691314fd_a12d4a7c9n12&sn=a12d4a7c9n12&time=1768728113&ver=2.0&vn=4.1.3.03281430&sign=6a1ee16242b93a3ae6492bc55992b691', + { + headers: { + 'Accept': '*/*', + 'User-Agent': 'RemoveUserAgent', + } + })).content; + d.push({ + title: 'req结果-60wmv', + content: html, + }); + return d; + }, + 一级: async () => { + return '这是一级:' + rule.title + }, + 二级: async () => { + return '这是二级:' + rule.title + }, + 搜索: async () => { + return ['这是搜索:' + rule.title] + }, + lazy: async () => { + return '这是播放:' + rule.title + }, +}; \ No newline at end of file diff --git a/spider/js/_lib.request.js b/spider/js/_lib.request.js index 8e9f85be..2df7a794 100644 --- a/spider/js/_lib.request.js +++ b/spider/js/_lib.request.js @@ -1,5 +1,19 @@ const iconv = require('iconv-lite'); +function sanitizeUserAgent(headers) { + if (!headers) { + return headers; + } + const keys = Object.keys(headers); + for (const key of keys) { + if (key.toLowerCase() === 'user-agent' && headers[key] === 'RemoveUserAgent') { + delete headers[key]; + break; + } + } + return headers; +} + async function requestHtml(url, options) { try { let html = (await req(url, options)).content; @@ -30,15 +44,20 @@ async function getPublicIp() { async function getHtml(config) { try { - return await axios.request(typeof config === "string" ? config : { + if (typeof config === "string") { + return await axios.request(config) + } + const cfg = { url: config.url, method: config.method || 'GET', headers: config.headers || { 'User-Agent': PC_UA }, data: config.data || '', - responseType: config.responseType || '',//'arraybuffer' - }) + responseType: config.responseType || '' + }; + cfg.headers = sanitizeUserAgent(cfg.headers); + return await axios.request(cfg) } catch (e) { return e.response } @@ -54,6 +73,7 @@ async function req_(reqUrl, mt, headers, data) { }, data: data || '', }; + config.headers = sanitizeUserAgent(config.headers); let res = await axios.request(config); return res.data; } @@ -68,6 +88,7 @@ async function req_encoding(reqUrl, mt, headers, encoding, data) { data: data || '', responseType: 'arraybuffer' }; + config.headers = sanitizeUserAgent(config.headers); let res = await axios.request(config); if (encoding) { res.data = iconv.decode(res.data, encoding); @@ -88,6 +109,7 @@ async function req_proxy(reqUrl, mt, headers, data) { port: "7890" } }; + config.headers = sanitizeUserAgent(config.headers); if (data) { config.data = data; } diff --git a/utils/createAxiosAgent.js b/utils/createAxiosAgent.js index 4c8f5599..ceb8bfdd 100644 --- a/utils/createAxiosAgent.js +++ b/utils/createAxiosAgent.js @@ -39,14 +39,27 @@ export function createAxiosInstance(options = {}) { const httpsAgent = new https.Agent(httpsAgentOptions); - // 配置 axios 使用代理 const _axios = axios.create({ - httpAgent, // 用于 HTTP 请求的代理 - httpsAgent, // 用于 HTTPS 请求的代理 + httpAgent, + httpsAgent, + }); + + _axios.interceptors.request.use(config => { + if (config && config.headers) { + const headers = config.headers; + const keys = Object.keys(headers); + for (const key of keys) { + if (key.toLowerCase() === 'user-agent' && headers[key] === 'RemoveUserAgent') { + delete headers[key]; + break; + } + } + } + return config; }); return _axios; } // 默认导出 -export default createAxiosInstance; \ No newline at end of file +export default createAxiosInstance; From de056c2092d25e38e80453b4349dbc9c2c6224f3 Mon Sep 17 00:00:00 2001 From: Taois Date: Sun, 18 Jan 2026 17:40:54 +0800 Subject: [PATCH 048/101] =?UTF-8?q?feat:=20=E9=81=BF=E5=85=8D=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E5=92=8C=E6=89=93=E5=8C=85=E4=B8=80=E4=BA=9B=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + package.js | 2 +- package.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 28c6287f..7bbca429 100644 --- a/.gitignore +++ b/.gitignore @@ -161,3 +161,4 @@ dist /apps/salary/ /jx/_30wmv.js .DS_Store +/spider/catvod/mtv60w[差].js diff --git a/package.js b/package.js index 1e52492e..6489562d 100644 --- a/package.js +++ b/package.js @@ -7,7 +7,7 @@ import url from 'url'; const EXCLUDE_DIRS = ['.git', '.idea', 'soft', 'examples', 'apps/cat', 'plugins/pvideo', 'plugins/req-proxy', 'plugins/pup-sniffer', 'plugins/mediaProxy', 'pyTools', 'drop_code', 'jstest', 'local', 'logs', '对话1.txt', 'vod_cache', 'data/mv']; // 要排除的文件列表 -const EXCLUDE_FILES = ['config/env.json', '.env', '.claude', 'clipboard.txt', 'clipboard.txt.bak', '.plugins.js', 'yarn.lock', 't4_daemon.pid', 'spider/js/UC分享.js', 'spider/js/百忙无果[官].js', 'json/UC分享.json', 'jx/_30wmv.js', 'jx/奇奇.js', 'jx/芒果关姐.js', 'data/settings/link_data.json', 'index.json', 'custom.json']; +const EXCLUDE_FILES = ['config/env.json', '.env', '.claude', 'clipboard.txt', 'clipboard.txt.bak', '.plugins.js', 'yarn.lock', 't4_daemon.pid', 'spider/js/UC分享.js', 'spider/js/百忙无果[官].js', 'spider/catvod/mtv60w[差].js', 'json/UC分享.json', 'jx/_30wmv.js', 'jx/奇奇.js', 'jx/芒果关姐.js', 'data/settings/link_data.json', 'index.json', 'custom.json']; // 获取脚本所在目录 const getScriptDir = () => dirname(resolve(url.fileURLToPath(import.meta.url))); diff --git a/package.py b/package.py index 827deca9..d34e7011 100644 --- a/package.py +++ b/package.py @@ -16,6 +16,7 @@ EXCLUDE_FILES = ['config/env.json', '.env', '.claude', 'clipboard.txt', 'clipboard.txt.bak', '.plugins.js', 'yarn.lock', 't4_daemon.pid', 'spider/js/UC分享.js', 'spider/js/百忙无果[官].js', + 'spider/catvod/mtv60w[差].js', 'json/UC分享.json', 'jx/_30wmv.js', 'jx/奇奇.js', 'jx/芒果关姐.js', 'data/settings/link_data.json', 'index.json', 'custom.json'] From 6d5f80ec520c59948ea4d30547ba76a0472ab8d1 Mon Sep 17 00:00:00 2001 From: Taois Date: Tue, 20 Jan 2026 19:26:01 +0800 Subject: [PATCH 049/101] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DhostName?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E9=94=99=E8=AF=AF=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=E5=85=B3=E5=A7=90=E5=9C=B0=E5=9D=80=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/file.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/utils/file.js b/utils/file.js index 07da6728..964b1dff 100644 --- a/utils/file.js +++ b/utils/file.js @@ -148,10 +148,21 @@ export function getParsesDict(host) { const jx_conf_text = readFileSync(jx_conf, 'utf-8'); let jx_conf_content = jx_conf_text.trim(); - // 准备模板变量字典 + let hostName = host; + try { + if (typeof host === 'string' && host) { + const u = new URL(host.includes('://') ? host : `http://${host}`); + hostName = u.hostname || host; + } + } catch (e) { + const withoutProto = String(host || '').replace(/^[a-zA-Z]+:\/\//, ''); + const withoutPath = withoutProto.split('/')[0]; + hostName = withoutPath.includes(':') ? withoutPath.split(':')[0] : withoutPath; + } + let var_dict = { host, - hostName: host.split(':').length > 1 ? host.slice(0, host.lastIndexOf(":")) : host + hostName }; // 使用Jinja模板引擎渲染配置内容 @@ -213,4 +224,4 @@ export function executeParse(name, host, url) { } globalThis.pathLib = pathLib; -globalThis.executeParse = executeParse; \ No newline at end of file +globalThis.executeParse = executeParse; From 968386782ad3ad0aefb79889aa14c803d28009e0 Mon Sep 17 00:00:00 2001 From: Taois Date: Tue, 20 Jan 2026 19:40:18 +0800 Subject: [PATCH 050/101] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DhostName?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E9=94=99=E8=AF=AF=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=E5=85=B3=E5=A7=90=E5=9C=B0=E5=9D=80=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/file.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/utils/file.js b/utils/file.js index 964b1dff..420e67a5 100644 --- a/utils/file.js +++ b/utils/file.js @@ -150,14 +150,15 @@ export function getParsesDict(host) { let hostName = host; try { - if (typeof host === 'string' && host) { - const u = new URL(host.includes('://') ? host : `http://${host}`); - hostName = u.hostname || host; - } + const raw = String(host || ''); + const hasScheme = raw.includes('://'); + const u = new URL(hasScheme ? raw : `http://${raw}`); + const hostname = u.hostname || raw; + const safeHostname = hostname.includes(':') ? `[${hostname}]` : hostname; + hostName = hasScheme ? `${u.protocol}//${safeHostname}` : safeHostname; } catch (e) { - const withoutProto = String(host || '').replace(/^[a-zA-Z]+:\/\//, ''); - const withoutPath = withoutProto.split('/')[0]; - hostName = withoutPath.includes(':') ? withoutPath.split(':')[0] : withoutPath; + const raw = String(host || '').replace(/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//, '').split('/')[0]; + hostName = raw.startsWith('[') ? raw.split(']')[0] + ']' : raw.split(':')[0]; } let var_dict = { From 4a0664f8d9303d9c049dc7fa93afa136f12ace61 Mon Sep 17 00:00:00 2001 From: Taois Date: Tue, 20 Jan 2026 21:14:07 +0800 Subject: [PATCH 051/101] =?UTF-8?q?feat:=E6=9B=B4=E6=96=B0=E4=B8=80?= =?UTF-8?q?=E6=B3=A2=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/parses.conf | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/config/parses.conf b/config/parses.conf index f150792d..95a61601 100644 --- a/config/parses.conf +++ b/config/parses.conf @@ -3,13 +3,14 @@ # 名称,链接,类型,ua,flag (ua不填默认 Mozilla/5.0) 可以手动填 Dart/2.14 (dart:io) # JSON解析排前面 -J1,https://zy.qiaoji8.com/gouzi.php?url=,1 -J2,https://jxjson.icu/neibu.php?url=,1 +J1,https://kalbim.xatut.top/kalbim2025/781718/play/video_player.php?url=,1 +J2,http://sspa8.top:8100/api/?key=1060089351&url=,1 # J3,http://pan.qiaoji8.com/tvbox/neibu.php?url=,1 # J4,http://yunhai.qijiyun.vip/home/api?type=ys&uid=177259&key=dijnouxKNOQSTUWXY5&url=,1 J芒果4k,http://mg.itufm.top/mg.php?url=,1 -HGvip,http://1.94.221.189:88/algorithm.php?url=,1 # J皮皮虾,http://45.207.215.101:5423/index.php?url=,1 +J腾讯关姐,{{hostName}}:5759/tencent.php/?url=,1 +# 295关姐,{{hostName}}:5759/295yun.php?url=,1 # WEB解析放后面 W花旗,https://www.huaqi.live/?url= @@ -18,15 +19,18 @@ W盘古,https://www.playm3u8.cn/jiexi.php?url= # W虾米,https://jx.xmflv.com/?url= # W无双,http://103.117.123.193:1980/players/?url= W1,https://jx.xymp4.cc/?url= -# W2,https://cdn.zyc888.top/?url= -# W3,https://yparse.ik9.cc/index.php?url= -# W4,https://jx.yparse.com/index.php?url= -# W5,https://jx.2s0.cn/player/?url= -# W6,https://jx.quankan.app/?url= +#W2,https://im1907.top/?jx= +W3,https://yparse.ik9.cc/index.php?url= +W4,https://jiexi.site/?url= +W5,https://jx.m3u8.tv/jiexi/?url= +W7,https://www.pangujiexi.com/jiexi/?url= +W8,https://www.pouyun.com/?url= +W9,https://jx.xmflv.com/?url= +Wa,https://jx.xmflv.cc/?url= +Wb,https://jx.yparse.com/index.php?url= +Wc,https://www.8090g.cn/?url= # W7,https://jx.aidouer.net/?url= # W8,https://www.8090g.cn/?url= # W9,https://jx.yangtu.top?url= # W10,https://jx.m3u8.tv/jiexi/?url= -W11,https://www.ckplayer.vip/jiexi/?url= -腾讯关姐,{{hostName}}:5759/tencent.php/?url=,1 -295关姐,{{hostName}}:5759/295yun.php?url=,1 +Wz,https://www.ckplayer.vip/jiexi/?url= From fe12e248712c5e0f6100a9e2b44aefb59e8c7c3e Mon Sep 17 00:00:00 2001 From: Taois Date: Tue, 20 Jan 2026 22:39:26 +0800 Subject: [PATCH 052/101] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E5=8F=A6?= =?UTF-8?q?=E7=B1=BB=E5=86=99=E6=B3=95=E7=9A=84cat=E6=BA=90=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/catvod.js | 10 +- libs_drpy/drpyInject.js | 50 ++- ...\345\223\251\345\223\251[\345\256\230].js" | 323 ++++++++++++++ ...\345\244\256\345\244\256[\345\256\230].js" | 290 +++++++++++++ ...\345\245\207\345\245\207[\345\256\230].js" | 403 ++++++++++++++++++ ...\346\236\234\346\236\234[\345\256\230].js" | 365 ++++++++++++++++ ...\351\205\267\351\205\267[\345\256\230].js" | 356 ++++++++++++++++ 7 files changed, 1792 insertions(+), 5 deletions(-) create mode 100644 "spider/catvod/\345\223\251\345\223\251[\345\256\230].js" create mode 100644 "spider/catvod/\345\244\256\345\244\256[\345\256\230].js" create mode 100644 "spider/catvod/\345\245\207\345\245\207[\345\256\230].js" create mode 100644 "spider/catvod/\346\236\234\346\236\234[\345\256\230].js" create mode 100644 "spider/catvod/\351\205\267\351\205\267[\345\256\230].js" diff --git a/libs/catvod.js b/libs/catvod.js index efb465cf..e9228e3c 100644 --- a/libs/catvod.js +++ b/libs/catvod.js @@ -184,10 +184,16 @@ const category = async function (filePath, env, tid, pg = 1, filter = 1, extend const detail = async function (filePath, env, ids) { const moduleObject = await init(filePath, env); const vod_id = Array.isArray(ids) ? ids[0] : ids; - return json2Object(await moduleObject.detail(vod_id)); + let detailResult = '{}'; + // console.log('type of detailContent:', typeof moduleObject.detailContent); + if (moduleObject.detailContent) { // tvbox形式猫源二级参数传ids列表 + detailResult = await moduleObject.detailContent(ids); + } else { // ds/cat传非id + detailResult = await moduleObject.detail(vod_id); + } + return json2Object(detailResult); } - const search = async function (filePath, env, wd, quick = 0, pg = 1) { const moduleObject = await init(filePath, env); return json2Object(await moduleObject.search(wd, quick, pg)); diff --git a/libs_drpy/drpyInject.js b/libs_drpy/drpyInject.js index 75d25c8c..b473ec13 100644 --- a/libs_drpy/drpyInject.js +++ b/libs_drpy/drpyInject.js @@ -163,10 +163,10 @@ async function request(url, opt = {}) { let effectivePostType = postType; if (!effectivePostType) { // 查找不区分大小写的 Content-Type 头 - const contentTypeKey = Object.keys(headers).find(key => + const contentTypeKey = Object.keys(headers).find(key => key.toLowerCase() === 'content-type' ); - + if (contentTypeKey && headers[contentTypeKey]) { const contentType = headers[contentTypeKey].toLowerCase(); if (contentType.includes('application/x-www-form-urlencoded')) { @@ -176,7 +176,7 @@ async function request(url, opt = {}) { } } } - + // 根据有效的 postType 处理数据 if (effectivePostType === 'form' && data != null && typeof data === 'object') { data = qs.stringify(data, {encode: false}); @@ -724,4 +724,48 @@ globalThis.jsonToCookie = jsonToCookie; globalThis.cookieToJson = cookieToJson; globalThis.keysToLowerCase = keysToLowerCase; +class BaseSpider { + constructor() { + this.home = this.homeContent; + this.category = this.categoryContent; + // this.detail = this.detailContent; + this.search = this.searchContent; + this.play = this.playerContent; + this.homeVod = this.homeVideoContent; + this.proxy = this.localProxy; + } + + async fetch(url, options) { + const content = (await req(url, options)).content; + return {data: content.parseX}; + } + + async homeContent() { + } + + async categoryContent() { + } + + async detailContent() { + } + + async searchContent() { + } + + async playerContent() { + } + + async homeVideoContent() { + } + + async localProxy() { + + } + + async action() { + + } +} + +globalThis.BaseSpider = BaseSpider; export default {}; diff --git "a/spider/catvod/\345\223\251\345\223\251[\345\256\230].js" "b/spider/catvod/\345\223\251\345\223\251[\345\256\230].js" new file mode 100644 index 00000000..df164c9c --- /dev/null +++ "b/spider/catvod/\345\223\251\345\223\251[\345\256\230].js" @@ -0,0 +1,323 @@ +/** + * 哔哩哔哩 - 猫影视JS爬虫格式 + * 调用壳子超级解析功能 + @header({ + searchable: 1, + filterable: 1, + quickSearch: 1, + title: 'B站', + lang: 'cat' + }) + */ + +class Spider extends BaseSpider { + + constructor() { + super(); + this.host = 'https://www.bilibili.com'; + this.headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + 'Referer': 'https://www.bilibili.com', + 'Accept': 'application/json, text/plain, */*', + 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8' + }; + + // B站Cookie(需要登录才能获取高清画质) + this.cookie = ""; + this.isLoggedIn = () => { + return this.cookie && this.cookie.includes("SESSDATA="); + }; + } + + init(extend = '') { + return ''; + } + + getName() { + return '哔哩哔哩'; + } + + isVideoFormat(url) { + return true; + } + + manualVideoCheck() { + return false; + } + + destroy() { + // 清理资源 + } + + homeContent(filter) { + const classes = [ + {type_id: '1', type_name: '番剧'}, + {type_id: '4', type_name: '国创'}, + {type_id: '2', type_name: '电影'}, + {type_id: '5', type_name: '电视剧'}, + {type_id: '3', type_name: '纪录片'}, + {type_id: '7', type_name: '综艺'} + ]; + + return { + class: classes + }; + } + + homeVideoContent() { + return {list: []}; + } + + async categoryContent(tid, pg, filter, extend) { + try { + const page = parseInt(pg) || 1; + let url = ''; + + if (['1', '4'].includes(tid)) { + url = `https://api.bilibili.com/pgc/web/rank/list?season_type=${tid}&pagesize=20&page=${page}&day=3`; + } else { + url = `https://api.bilibili.com/pgc/season/rank/web/list?season_type=${tid}&pagesize=20&page=${page}&day=3`; + } + + const headers = {...this.headers}; + if (this.cookie) { + headers.Cookie = this.cookie; + } + + const response = await this.fetch(url, {}, headers); + const data = response.data || {}; + + const videos = []; + if (data.code === 0) { + const vodList = data.result ? data.result.list : (data.data ? data.data.list : []); + + for (const vod of vodList) { + const title = vod.title ? vod.title.trim() : ''; + if (title.includes('预告')) { + continue; + } + + const remark = vod.new_ep ? vod.new_ep.index_show : vod.index_show; + + // 处理封面图片 + let cover = vod.cover || ''; + if (cover && cover.startsWith('//')) { + cover = 'https:' + cover; + } + + videos.push({ + vod_id: vod.season_id ? vod.season_id.toString() : '', + vod_name: title, + vod_pic: cover, + vod_remarks: remark || '' + }); + } + } + + return { + list: videos, + page: page, + pagecount: videos.length === 20 ? page + 1 : page, + limit: 20, + total: 9999 + }; + + } catch (error) { + console.error(`categoryContent error: ${error.message}`); + return { + list: [], + page: pg, + pagecount: 0, + limit: 20, + total: 0 + }; + } + } + + formatCount(num) { + if (num > 1e8) return (num / 1e8).toFixed(2) + '亿'; + if (num > 1e4) return (num / 1e4).toFixed(2) + '万'; + return num.toString(); + } + + async detailContent(ids) { + try { + const seasonId = ids[0]; + + const headers = {...this.headers}; + if (this.cookie) { + headers.Cookie = this.cookie; + } + + const url = `https://api.bilibili.com/pgc/view/web/season?season_id=${seasonId}`; + const response = await this.fetch(url, {}, headers); + const data = response.data || {}; + + if (data.code !== 0) { + return {list: []}; + } + + const res = data.result; + const stat = res.stat || {}; + + // 处理封面图片 + let cover = res.cover || ''; + if (cover && cover.startsWith('//')) { + cover = 'https:' + cover; + } + + const vod = { + vod_id: res.season_id ? res.season_id.toString() : '', + vod_name: res.title || '', + vod_pic: cover, + type_name: res.share_sub_title || res.type_name || '', + vod_year: res.publish && res.publish.pub_time ? res.publish.pub_time.substr(0, 4) : '', + vod_area: res.areas && res.areas.length > 0 ? res.areas[0].name : '', + vod_actor: `点赞:${this.formatCount(stat.likes || 0)} 投币:${this.formatCount(stat.coins || 0)}`, + vod_content: res.evaluate || res.new_ep?.desc || '', + vod_director: res.rating ? `评分:${res.rating.score}` : '暂无评分', + vod_play_from: '哔哩哔哩', + vod_play_url: '' + }; + + // 过滤预告片,构建播放列表 + const episodes = (res.episodes || []).filter(ep => !ep.title.includes('预告')); + const playUrls = []; + + for (const ep of episodes) { + const title = `${ep.title.replace(/#/g, '-')} ${ep.long_title || ''}`; + const playId = `${res.season_id}_${ep.id}_${ep.cid}`; + playUrls.push(`${title}$${playId}`); + } + + vod.vod_play_url = playUrls.join('#'); + + return {list: [vod]}; + + } catch (error) { + console.error(`detailContent error: ${error.message}`); + return {list: []}; + } + } + + async searchContent(key, quick, pg = '1') { + try { + const page = parseInt(pg) || 1; + const encodedKeyword = encodeURIComponent(key); + const searchTypes = ['media_bangumi', 'media_ft']; + + const headers = {...this.headers}; + if (this.cookie) { + headers.Cookie = this.cookie; + } + + const allVideos = []; + + for (const type of searchTypes) { + try { + const url = `https://api.bilibili.com/x/web-interface/search/type?search_type=${type}&keyword=${encodedKeyword}&page=${page}`; + const response = await this.fetch(url, {}, headers); + const data = response.data || {}; + + if (data.code === 0 && data.data && data.data.result) { + for (const vod of data.data.result) { + const title = vod.title ? vod.title.replace(/<[^>]+>/g, '') : ''; + if (title.includes('预告')) { + continue; + } + + // 处理封面图片 + let cover = vod.cover || ''; + if (cover && cover.startsWith('//')) { + cover = 'https:' + cover; + } + + allVideos.push({ + vod_id: vod.season_id ? vod.season_id.toString() : '', + vod_name: title, + vod_pic: cover, + vod_remarks: vod.index_show || '' + }); + } + } + } catch (searchError) { + console.error(`搜索类型 ${type} 失败: ${searchError.message}`); + } + } + + return { + list: allVideos, + page: page, + pagecount: allVideos.length > 0 ? page + 1 : page, + limit: 20, + total: allVideos.length + }; + + } catch (error) { + console.error(`searchContent error: ${error.message}`); + return { + list: [], + page: pg, + pagecount: 0, + limit: 20, + total: 0 + }; + } + } + + async playerContent(flag, id, vipFlags) { + try { + // 哔哩哔哩有自己的解析逻辑,直接返回播放链接 + // 格式:seasonId_epId_cid + const parts = id.split('_'); + if (parts.length < 3) { + throw new Error('无效的播放ID格式'); + } + + const seasonId = parts[0]; + const epId = parts[1]; + const cid = parts[2]; + + // 构建播放链接(原版B站链接) + const playUrl = `https://www.bilibili.com/bangumi/play/ep${epId}`; + + // 调用壳子超级解析 + const playData = { + parse: 1, + jx: 1, + play_parse: true, + parse_type: '壳子超级解析', + parse_source: '哔哩哔哩', + url: playUrl, + header: JSON.stringify({ + 'User-Agent': this.headers['User-Agent'], + 'Referer': 'https://www.bilibili.com', + 'Origin': 'https://www.bilibili.com', + 'Cookie': this.cookie || '' + }) + }; + + return playData; + + } catch (error) { + console.error(`playerContent error: ${error.message}`); + // 即使出错也返回超级解析参数 + return { + parse: 1, + jx: 1, + play_parse: true, + parse_type: '壳子超级解析', + parse_source: '哔哩哔哩', + url: id.includes('_') ? `https://www.bilibili.com/bangumi/play/ep${id.split('_')[1]}` : id, + header: JSON.stringify(this.headers) + }; + } + } + + localProxy(param) { + return null; + } +} + + +export default new Spider(); \ No newline at end of file diff --git "a/spider/catvod/\345\244\256\345\244\256[\345\256\230].js" "b/spider/catvod/\345\244\256\345\244\256[\345\256\230].js" new file mode 100644 index 00000000..895aea15 --- /dev/null +++ "b/spider/catvod/\345\244\256\345\244\256[\345\256\230].js" @@ -0,0 +1,290 @@ +/** + * 央视大全 - 猫影视/TVBox JS爬虫格式 + * 继承BaseSpider类 + @header({ + searchable: 1, + filterable: 1, + quickSearch: 1, + title: '央视大全', + lang: 'cat' + }) + */ + +class Spider extends BaseSpider { + + constructor() { + super(); + this.host = 'https://api.cntv.cn'; + this.siteName = '央视大全'; + this.sessionStore = {}; + this.videoCache = {}; + + this.headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "Referer": "https://tv.cctv.com", + "Accept": "application/json, text/plain, */*", + "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8" + }; + } + + init(extend = "") { + return ""; + } + + getName() { + return this.siteName; + } + + isVideoFormat(url) { + return url.includes('.m3u8') || url.includes('.mp4'); + } + + manualVideoCheck() { + return false; + } + + destroy() { + this.sessionStore = {}; + this.videoCache = {}; + } + + homeContent(filter) { + const categories = [ + {type_id: "栏目大全", type_name: "栏目大全"}, + {type_id: "特别节目", type_name: "特别节目"}, + {type_id: "纪录片", type_name: "纪录片"}, + {type_id: "电视剧", type_name: "电视剧"}, + {type_id: "动画片", type_name: "动画片"} + ]; + + return {class: categories}; + } + + async homeVideoContent() { + // 央视首页推荐 + return {list: []}; + } + + async categoryContent(tid, pg, filter, extend) { + try { + const page = parseInt(pg) || 1; + const videos = []; + + const channelMap = { + "特别节目": "CHAL1460955953877151", + "纪录片": "CHAL1460955924871139", + "电视剧": "CHAL1460955853485115", + "动画片": "CHAL1460955899450127", + }; + + let filterObj = {}; + if (extend && typeof extend === 'object') { + filterObj = extend; + } + + if (tid === '栏目大全') { + const url = `${this.host}/lanmu/columnSearch?&fl=&fc=&cid=&p=${page}&n=20&serviceId=tvcctv&t=json`; + const response = await this.fetch(url, {}, this.headers); + const data = response.data; + + if (data && data.response && data.response.docs) { + const docs = data.response.docs; + docs.forEach(it => { + videos.push({ + vod_id: `${it.lastVIDE.videoSharedCode}|${it.column_firstclass}|${it.column_name}|${it.channel_name}|${it.column_brief}|${it.column_logo}|${it.lastVIDE.videoTitle}|栏目大全`, + vod_name: it.column_name, + vod_pic: it.column_logo, + vod_remarks: it.channel_name, + vod_content: '' + }); + }); + } + } else { + // 处理筛选参数 + let fl_url = `&channelid=${channelMap[tid] || ''}&fc=${encodeURIComponent(tid)}`; + if (filterObj.channel) fl_url += `&channel=${encodeURIComponent(filterObj.channel)}`; + if (filterObj.sc) fl_url += `&sc=${encodeURIComponent(filterObj.sc)}`; + if (filterObj.year) fl_url += `&year=${filterObj.year}`; + + const url = `${this.host}/list/getVideoAlbumList?${fl_url}&area=&letter=&n=24&serviceId=tvcctv&t=json&p=${page}`; + const response = await this.fetch(url, {}, this.headers); + const data = response.data; + + if (data && data.data && data.data.list) { + const dataList = data.data.list; + dataList.forEach(it => { + videos.push({ + vod_id: `${it.id}|${it.sc}|${it.title}|${it.channel}|${it.brief}|${it.image}|${it.count}|${tid}`, + vod_name: it.title, + vod_pic: it.image, + vod_remarks: `${it.sc}${it.year ? '·' + it.year : ''}`, + vod_content: it.brief || '' + }); + }); + } + } + + return { + list: videos, + page: page, + pagecount: 9999, + limit: 20, + total: 999999 + }; + + } catch (error) { + console.error(`categoryContent error: ${error.message}`); + return { + list: [], + page: pg, + pagecount: 0, + limit: 20, + total: 0 + }; + } + } + + async detailContent(ids) { + try { + const id = ids[0]; + if (!id) return {list: []}; + + // 检查缓存 + const cacheKey = `detail_${id}`; + if (this.videoCache[cacheKey]) { + return {list: [this.videoCache[cacheKey]]}; + } + + const info = id.split("|"); + // ID 结构: 0:id, 1:sc, 2:title, 3:channel, 4:brief, 5:image, 6:count/remark, 7:cate + + const cate = info[7]; + const ctid = info[0]; + const modeMap = { + "特别节目": "0", + "纪录片": "0", + "电视剧": "0", + "动画片": "1" + }; + + // 获取选集列表 + let playUrls = []; + const mode = modeMap[cate] || '0'; + const albumUrl = `${this.host}/NewVideo/getVideoListByAlbumIdNew?id=${ctid}&serviceId=tvcctv&p=1&n=100&mode=${mode}&pub=1`; + + const response = await this.fetch(albumUrl, {}, this.headers); + const data = response.data; + + if (data.errcode === '1001') { + // 需要获取真实的ctid + const videoInfoUrl = `${this.host}/video/videoinfoByGuid?guid=${ctid}&serviceId=tvcctv`; + const vInfoRes = await this.fetch(videoInfoUrl, {}, this.headers); + const vInfoData = vInfoRes.data; + const realCtid = vInfoData.ctid; + + const columnUrl = `${this.host}/NewVideo/getVideoListByColumn?id=${realCtid}&d=&p=1&n=100&sort=desc&mode=0&serviceId=tvcctv&t=json`; + const colRes = await this.fetch(columnUrl, {}, this.headers); + const colData = colRes.data; + playUrls = colData.data?.list || []; + } else { + playUrls = data.data?.list || []; + } + + // 构建播放列表 + const playList = []; + if (playUrls.length > 0) { + for (const item of playUrls) { + const title = item.title || `第${item.index || '?'}集`; + const cleanTitle = title.replace(/\$/g, ''); + const guid = item.guid || ''; + playList.push(`${cleanTitle}$${guid}`); + } + } + + const vod = { + vod_id: id, + vod_name: info[2] || '', + vod_pic: info[5] || '', + type_name: info[1] || '', + vod_year: '', + vod_area: '', + vod_remarks: info[6] ? `共${info[6]}集` : '', + vod_actor: '', + vod_director: '', + vod_content: info[4] || '', + vod_play_from: playList.length > 0 ? '央视频' : '', + vod_play_url: playList.length > 0 ? playList.join('#') : '' + }; + + // 缓存结果 + this.videoCache[cacheKey] = vod; + + return {list: [vod]}; + + } catch (error) { + console.error(`detailContent error: ${error.message}`); + return {list: []}; + } + } + + async searchContent(key, quick, pg = "1") { + // CCTV搜索接口较复杂,这里返回空结果 + return { + list: [], + page: pg, + pagecount: 0, + limit: 20, + total: 0 + }; + } + + async playerContent(flag, id, vipFlags) { + try { + // 央视视频采用直接播放的方式 + // 根据GUID拼接m3u8地址 + let playUrl = `https://cntv.playdreamer.cn/proxy/asp/hls/2000/0303000a/3/default/${id}/2000.m3u8`; + + // 也可以尝试其他格式 + // playUrl = `https://hls.cntv.myalicdn.com/asp/hls/2000/0303000a/3/default/${id}/2000.m3u8`; + + return { + parse: 0, // 0表示直接播放,不需要解析 + jx: 0, // 0表示不解析 + url: playUrl, + header: JSON.stringify({ + 'User-Agent': this.headers['User-Agent'], + 'Referer': 'https://tv.cctv.com', + 'Origin': 'https://tv.cctv.com' + }) + }; + + } catch (error) { + console.error(`playerContent error: ${error.message}`); + return { + parse: 0, + jx: 0, + url: id, + header: JSON.stringify(this.headers) + }; + } + } + + localProxy(param) { + return null; + } + + // 辅助方法:安全获取对象属性 + getSafe(obj, path, defaultValue = '') { + if (!obj || typeof obj !== 'object') return defaultValue; + try { + return path.split('.').reduce((o, key) => { + if (o == null) return defaultValue; + return o[key]; + }, obj) ?? defaultValue; + } catch { + return defaultValue; + } + } +} + +export default new Spider(); \ No newline at end of file diff --git "a/spider/catvod/\345\245\207\345\245\207[\345\256\230].js" "b/spider/catvod/\345\245\207\345\245\207[\345\256\230].js" new file mode 100644 index 00000000..956ed6b1 --- /dev/null +++ "b/spider/catvod/\345\245\207\345\245\207[\345\256\230].js" @@ -0,0 +1,403 @@ +/** + * 爱奇艺视频 - 猫影视/TVBox JS爬虫格式 + * 调用壳子超级解析功能(壳子会自动读取json配置) + @header({ + searchable: 1, + filterable: 1, + quickSearch: 1, + title: '爱奇艺视频', + lang: 'cat' + }) + */ + +class Spider extends BaseSpider { + + constructor() { + super(); + this.host = 'https://www.iqiyi.com'; + this.sessionStore = {}; + + this.headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + 'Referer': 'https://www.iqiyi.com', + 'Accept': 'application/json, text/plain, */*', + 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive' + }; + + // 分类配置 + this.classes = [ + {type_id: '1', type_name: '电影'}, + {type_id: '2', type_name: '电视剧'}, + {type_id: '6', type_name: '综艺'}, + {type_id: '4', type_name: '动漫'}, + {type_id: '3', type_name: '纪录片'}, + {type_id: '5', type_name: '音乐'}, + {type_id: '16', type_name: '网络电影'} + ]; + + // 筛选配置 + this.filters = { + '1': [{ + key: 'year', + name: '年代', + value: [{n: '全部', v: ''}, {n: '2025', v: '2025'}, {n: '2024', v: '2024'}, {n: '2023', v: '2023'}] + }], + '2': [{ + key: 'year', + name: '年代', + value: [{n: '全部', v: ''}, {n: '2025', v: '2025'}, {n: '2024', v: '2024'}, {n: '2023', v: '2023'}] + }] + }; + } + + init(extend = '') { + return ''; + } + + getName() { + return '爱奇艺视频'; + } + + isVideoFormat(url) { + return true; + } + + manualVideoCheck() { + return false; + } + + destroy() { + // 清理资源 + } + + homeContent(filter) { + const result = { + class: this.classes, + filters: this.filters + }; + + return result; + } + + homeVideoContent() { + return {list: []}; + } + + async categoryContent(tid, pg, filter, extend) { + try { + let channelId = tid; + let dataType = 1; + let extraParams = ""; + const page = parseInt(pg) || 1; + + if (tid === "16") { + channelId = "1"; + extraParams = "&three_category_id=27401"; + } else if (tid === "5") { + dataType = 2; + } + + // 处理筛选条件 + if (extend) { + let extendObj = {}; + if (typeof extend === 'string') { + try { + extendObj = JSON.parse(extend); + } catch (e) { + // 如果不是JSON,尝试解析为key=value格式 + extend.split('&').forEach(item => { + const [key, value] = item.split('='); + if (key && value) { + extendObj[key] = value; + } + }); + } + } else if (typeof extend === 'object') { + extendObj = extend; + } + + if (extendObj.year) { + extraParams += `&market_release_date_level=${extendObj.year}`; + } + } + + const url = `https://pcw-api.iqiyi.com/search/recommend/list?channel_id=${channelId}&data_type=${dataType}&page_id=${page}&ret_num=20${extraParams}`; + + const response = await this.fetch(url, {}, this.headers); + const jsonData = response.data; + + const videos = []; + if (jsonData.data && jsonData.data.list) { + for (const item of jsonData.data.list) { + const vid = `${item.channelId}$${item.albumId}`; + let remarks = ""; + + if (item.channelId === 1) { + remarks = item.score ? `${item.score}分` : ""; + } else if (item.channelId === 2 || item.channelId === 4) { + if (item.latestOrder && item.videoCount) { + remarks = item.latestOrder === item.videoCount ? + `${item.latestOrder}集全` : + `更新至${item.latestOrder}集`; + } else { + remarks = item.focus || ""; + } + } else { + remarks = item.period || item.focus || ""; + } + + videos.push({ + vod_id: vid, + vod_name: item.name, + vod_pic: item.imageUrl ? item.imageUrl.replace(".jpg", "_390_520.jpg") : "", + vod_remarks: remarks + }); + } + } + + return { + list: videos, + page: page, + pagecount: 9999, + limit: 20, + total: 999999 + }; + + } catch (error) { + console.error(`categoryContent error: ${error.message}`); + return { + list: [], + page: pg, + pagecount: 0, + limit: 20, + total: 0 + }; + } + } + + async getPlaylists(channelId, albumId, data) { + let playlists = []; + const cid = parseInt(channelId || data.channelId || 0); + + try { + if (cid === 1 || cid === 5) { + // 电影或音乐 + if (data.playUrl) { + playlists.push({title: data.name || '正片', url: data.playUrl}); + } + } else if (cid === 6 && data.period) { + // 综艺 + let qs = data.period.toString().split("-")[0]; + let listUrl = `https://pcw-api.iqiyi.com/album/source/svlistinfo?cid=6&sourceid=${albumId}&timelist=${qs}`; + try { + const listResp = await this.fetch(listUrl, {}, this.headers); + const listJson = listResp.data; + if (listJson.data && listJson.data[qs]) { + listJson.data[qs].forEach(it => { + playlists.push({ + title: it.shortTitle || it.period || it.focus || `期${it.order}`, + url: it.playUrl + }); + }); + } + } catch (e) { + console.error(`综艺列表获取失败: ${e.message}`); + } + } else { + // 电视剧、动漫等 + let listUrl = `https://pcw-api.iqiyi.com/albums/album/avlistinfo?aid=${albumId}&size=100&page=1`; + try { + const listResp = await this.fetch(listUrl, {}, this.headers); + const listJson = listResp.data; + + if (listJson.data && listJson.data.epsodelist) { + playlists = listJson.data.epsodelist.map(item => ({ + title: item.shortTitle || item.title || + (item.order ? `第${item.order}集` : `集${item.timelist}`), + url: item.playUrl || item.url || '' + })); + + // 处理分页 + const total = listJson.data.total; + if (total > 100) { + const totalPages = Math.ceil(total / 100); + for (let i = 2; i <= totalPages; i++) { + let nextUrl = `https://pcw-api.iqiyi.com/albums/album/avlistinfo?aid=${albumId}&size=100&page=${i}`; + try { + const nextResp = await this.fetch(nextUrl, {}, this.headers); + const nextJson = nextResp.data; + if (nextJson.data && nextJson.data.epsodelist) { + playlists = playlists.concat(nextJson.data.epsodelist.map(item => ({ + title: item.shortTitle || item.title || + (item.order ? `第${item.order}集` : `集${item.timelist}`), + url: item.playUrl || item.url || '' + }))); + } + } catch (e) { + break; + } + } + } + } + } catch (e) { + console.error(`剧集列表获取失败: ${e.message}`); + } + } + } catch (error) { + console.error(`getPlaylists error: ${error.message}`); + } + + return playlists; + } + + async detailContent(ids) { + try { + const id = ids[0]; + let channelId = ""; + let albumId = id; + + if (id.includes('$')) { + const parts = id.split('$'); + channelId = parts[0]; + albumId = parts[1]; + } + + // 获取视频基本信息 + const infoUrl = `https://pcw-api.iqiyi.com/video/video/videoinfowithuser/${albumId}?agent_type=1&authcookie=&subkey=${albumId}&subscribe=1`; + const infoResp = await this.fetch(infoUrl, {}, this.headers); + const infoJson = infoResp.data; + const data = infoJson.data || {}; + + // 获取播放列表 + const playlists = await this.getPlaylists(channelId, albumId, data); + + // 构建播放地址 + const playUrls = []; + if (playlists.length > 0) { + for (const item of playlists) { + if (item.url) { + playUrls.push(`${item.title}$${item.url}`); + } + } + } + + const vod = { + vod_id: id, + vod_name: data.name || '未知标题', + type_name: data.categories ? data.categories.map(it => it.name).join(',') : '', + vod_year: data.formatPeriod || '', + vod_area: data.areas ? data.areas.map(it => it.name).join(',') : '', + vod_remarks: data.latestOrder ? + `更新至${data.latestOrder}集` : + (data.period || playlists.length > 0 ? `${playlists.length}集` : ''), + vod_actor: data.people && data.people.main_charactor ? + data.people.main_charactor.map(it => it.name).join(',') : '', + vod_director: data.people && data.people.director ? + data.people.director.map(it => it.name).join(',') : '', + vod_content: data.description || '暂无简介', + vod_pic: data.imageUrl ? data.imageUrl.replace(".jpg", "_480_270.jpg") : '', + vod_play_from: playUrls.length > 0 ? '爱奇艺视频' : '', + vod_play_url: playUrls.length > 0 ? playUrls.join('#') : '' + }; + + return {list: [vod]}; + + } catch (error) { + console.error(`detailContent error: ${error.message}`); + return {list: []}; + } + } + + async searchContent(key, quick, pg = '1') { + try { + const page = parseInt(pg) || 1; + const url = `https://search.video.iqiyi.com/o?if=html5&key=${encodeURIComponent(key)}&pageNum=${page}&pos=1&pageSize=20&site=iqiyi`; + + const response = await this.fetch(url, {}, this.headers); + const jsonData = response.data; + + const videos = []; + + if (jsonData.data && jsonData.data.docinfos) { + for (const item of jsonData.data.docinfos) { + if (item.albumDocInfo) { + const doc = item.albumDocInfo; + const channelId = doc.channel ? doc.channel.split(',')[0] : '0'; + videos.push({ + vod_id: `${channelId}$${doc.albumId}`, + vod_name: doc.albumTitle || '', + vod_pic: doc.albumVImage || '', + vod_remarks: doc.tvFocus || doc.year || '' + }); + } + } + } + + return { + list: videos, + page: page, + pagecount: 10, + limit: 20, + total: videos.length + }; + + } catch (error) { + console.error(`searchContent error: ${error.message}`); + return { + list: [], + page: pg, + pagecount: 0, + limit: 20, + total: 0 + }; + } + } + + async playerContent(flag, id, vipFlags) { + try { + // 解析播放地址 + let playUrl = id; + if (id.includes('$')) { + playUrl = id.split('$')[1]; + } + + // 关键:调用壳子超级解析 + const playData = { + parse: 1, // 必须为1,表示需要解析 + jx: 1, // 必须为1,启用解析 + play_parse: true, // 启用播放解析 + parse_type: '壳子超级解析', + parse_source: '爱奇艺视频', + url: playUrl, // 原始爱奇艺链接 + header: JSON.stringify({ + 'User-Agent': this.headers['User-Agent'], + 'Referer': 'https://www.iqiyi.com', + 'Origin': 'https://www.iqiyi.com' + }) + }; + + return playData; + + } catch (error) { + console.error(`playerContent error: ${error.message}`); + // 即使出错也返回超级解析参数,让壳子处理 + return { + parse: 1, + jx: 1, + play_parse: true, + parse_type: '壳子超级解析', + parse_source: '爱奇艺视频', + url: id, + header: JSON.stringify(this.headers) + }; + } + } + + localProxy(param) { + return null; + } +} + +export default new Spider(); \ No newline at end of file diff --git "a/spider/catvod/\346\236\234\346\236\234[\345\256\230].js" "b/spider/catvod/\346\236\234\346\236\234[\345\256\230].js" new file mode 100644 index 00000000..33f6e159 --- /dev/null +++ "b/spider/catvod/\346\236\234\346\236\234[\345\256\230].js" @@ -0,0 +1,365 @@ +/** + * 芒果TV - 猫影视JS爬虫格式(第二个版本) + * 调用壳子超级解析功能 + @header({ + searchable: 1, + filterable: 1, + quickSearch: 1, + title: '芒果TV', + lang: 'cat' + }) + */ + +class Spider extends BaseSpider { + + constructor() { + super(); + this.host = 'https://www.mgtv.com'; + this.headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', + 'Referer': 'https://www.mgtv.com/', + 'Accept': 'application/json, text/plain, */*', + 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive' + }; + } + + init(extend = '') { + return ''; + } + + getName() { + return '芒果TV2'; + } + + isVideoFormat(url) { + return true; + } + + manualVideoCheck() { + return false; + } + + destroy() { + // 清理资源 + } + + homeContent(filter) { + const classes = [ + {type_id: '3', type_name: '电影'}, + {type_id: '2', type_name: '电视剧'}, + {type_id: '1', type_name: '综艺'}, + {type_id: '50', type_name: '动漫'}, + {type_id: '51', type_name: '纪录片'}, + {type_id: '115', type_name: '教育'}, + {type_id: '10', type_name: '少儿'} + ]; + + const filters = { + '3': [ + { + key: 'year', name: '年份', value: [ + {n: '全部', v: 'all'}, {n: '2025', v: '2025'}, {n: '2024', v: '2024'}, + {n: '2023', v: '2023'}, {n: '2022', v: '2022'}, {n: '2021', v: '2021'}, + {n: '2020', v: '2020'}, {n: '2019', v: '2019'}, {n: '2010-2019', v: '2010-2019'}, + {n: '2000-2009', v: '2000-2009'} + ] + }, + { + key: 'sort', name: '排序', value: [ + {n: '综合', v: 'c1'}, {n: '最新', v: 'c2'}, {n: '最热', v: 'c4'} + ] + } + ], + '2': [ + { + key: 'year', name: '年份', value: [ + {n: '全部', v: 'all'}, {n: '2025', v: '2025'}, {n: '2024', v: '2024'}, + {n: '2023', v: '2023'}, {n: '2022', v: '2022'}, {n: '2021', v: '2021'}, + {n: '2020', v: '2020'} + ] + }, + { + key: 'sort', name: '排序', value: [ + {n: '综合', v: 'c1'}, {n: '最新', v: 'c2'}, {n: '最热', v: 'c4'} + ] + } + ], + '1': [ + { + key: 'sort', name: '排序', value: [ + {n: '综合', v: 'c1'}, {n: '最新', v: 'c2'}, {n: '最热', v: 'c4'} + ] + } + ], + '50': [ + { + key: 'sort', name: '排序', value: [ + {n: '综合', v: 'c1'}, {n: '最新', v: 'c2'}, {n: '最热', v: 'c4'} + ] + } + ] + }; + + return { + class: classes, + filters: filters + }; + } + + homeVideoContent() { + return {list: []}; + } + + async categoryContent(tid, pg, filter, extend) { + try { + const page = parseInt(pg) || 1; + const baseUrl = 'https://pianku.api.mgtv.com/rider/list/pcweb/v3'; + + // 构建查询参数 + const params = { + platform: 'pcweb', + channelId: tid, + pn: page, + pc: '20', + hudong: '1', + _support: '10000000', + kind: 'a1', + area: 'a1' + }; + + // 处理筛选条件 + if (extend) { + if (extend.year && extend.year !== 'all') { + params.year = extend.year; + } + if (extend.sort) { + params.sort = extend.sort; + } + if (extend.chargeInfo) { + params.chargeInfo = extend.chargeInfo; + } + } + + const queryString = new URLSearchParams(params).toString(); + const url = `${baseUrl}?${queryString}`; + + const response = await this.fetch(url, {}, this.headers); + const json = response.data || {}; + + const videos = []; + if (json.data?.hitDocs && Array.isArray(json.data.hitDocs)) { + for (const item of json.data.hitDocs) { + videos.push({ + vod_id: item.playPartId || '', + vod_name: item.title || '', + vod_pic: item.img || '', + vod_remarks: item.updateInfo || item.rightCorner?.text || '' + }); + } + } + + return { + list: videos, + page: page, + pagecount: json.data?.totalPage || 999, + limit: 20, + total: json.data?.totalHit || 9999 + }; + + } catch (error) { + console.error(`categoryContent error: ${error.message}`); + return { + list: [], + page: pg, + pagecount: 0, + limit: 20, + total: 0 + }; + } + } + + async detailContent(ids) { + try { + const videoId = ids[0]; + + // 获取视频基本信息 + const infoUrl = `https://pcweb.api.mgtv.com/video/info?video_id=${videoId}`; + const infoResponse = await this.fetch(infoUrl, {}, this.headers); + const infoData = infoResponse.data?.data?.info || {}; + + const vod = { + vod_id: videoId, + vod_name: infoData.title || '', + type_name: infoData.root_kind || '', + vod_actor: '', + vod_year: infoData.release_time || '', + vod_content: infoData.desc || '', + vod_remarks: infoData.time || '', + vod_pic: infoData.img || '', + vod_play_from: '芒果TV', + vod_play_url: '' + }; + + // 分页获取所有剧集 + const pageSize = 50; + let allEpisodes = []; + + try { + // 获取第一页,同时获取总页数 + const firstPageUrl = `https://pcweb.api.mgtv.com/episode/list?video_id=${videoId}&page=1&size=${pageSize}`; + const firstResponse = await this.fetch(firstPageUrl, {}, this.headers); + const firstData = firstResponse.data?.data || {}; + + if (firstData.list && Array.isArray(firstData.list)) { + allEpisodes = allEpisodes.concat(firstData.list); + const totalPages = firstData.total_page || 1; + + // 如果有多页,获取剩余页面 + if (totalPages > 1) { + const pagePromises = []; + for (let i = 2; i <= totalPages; i++) { + const pageUrl = `https://pcweb.api.mgtv.com/episode/list?video_id=${videoId}&page=${i}&size=${pageSize}`; + pagePromises.push(this.fetch(pageUrl, {}, this.headers)); + } + + const responses = await Promise.all(pagePromises); + for (const response of responses) { + const data = response.data?.data || {}; + if (data.list && Array.isArray(data.list)) { + allEpisodes = allEpisodes.concat(data.list); + } + } + } + } + } catch (episodeError) { + console.error(`获取剧集列表失败: ${episodeError.message}`); + } + + // 构建播放列表 + const playUrls = []; + if (allEpisodes.length > 0) { + // 过滤可播放的剧集(isIntact = 1) + const validEpisodes = allEpisodes.filter(item => + item.isIntact === "1" || item.isIntact === 1 + ); + + // 按集数排序 + validEpisodes.sort((a, b) => { + const orderA = parseInt(a.order) || 0; + const orderB = parseInt(b.order) || 0; + return orderA - orderB; + }); + + // 构建播放链接 + for (const item of validEpisodes) { + const name = item.t4 || item.t3 || item.title || `第${item.order || '?'}集`; + const playLink = item.url ? `https://www.mgtv.com${item.url}` : ''; + + if (playLink) { + playUrls.push(`${name}$${playLink}`); + } + } + } + + vod.vod_play_url = playUrls.join('#'); + + return {list: [vod]}; + + } catch (error) { + console.error(`detailContent error: ${error.message}`); + return {list: []}; + } + } + + async searchContent(key, quick, pg = '1') { + try { + const page = parseInt(pg) || 1; + const searchUrl = `https://mobileso.bz.mgtv.com/msite/search/v2?q=${encodeURIComponent(key)}&pn=${page}&pc=20`; + + const response = await this.fetch(searchUrl, {}, this.headers); + const json = response.data?.data || {}; + + const videos = []; + + if (json.contents && Array.isArray(json.contents)) { + for (const group of json.contents) { + if (group.type === 'media' && group.data && Array.isArray(group.data)) { + for (const item of group.data) { + if (item.source === 'imgo') { + // 提取视频ID + const match = item.url.match(/\/(\d+)\.html/); + if (match) { + videos.push({ + vod_id: match[1], + vod_name: item.title ? item.title.replace(/|<\/B>/g, '') : '', + vod_pic: item.img || '', + vod_remarks: item.desc ? item.desc.join(' ') : '' + }); + } + } + } + } + } + } + + return { + list: videos, + page: page, + pagecount: 10, + limit: 20, + total: videos.length + }; + + } catch (error) { + console.error(`searchContent error: ${error.message}`); + return { + list: [], + page: pg, + pagecount: 0, + limit: 20, + total: 0 + }; + } + } + + async playerContent(flag, id, vipFlags) { + try { + // 调用壳子超级解析 + const playData = { + parse: 1, + jx: 1, + play_parse: true, + parse_type: '壳子超级解析', + parse_source: '芒果TV2', + url: id, + header: JSON.stringify({ + 'User-Agent': this.headers['User-Agent'], + 'Referer': 'https://www.mgtv.com', + 'Origin': 'https://www.mgtv.com' + }) + }; + + return playData; + + } catch (error) { + console.error(`playerContent error: ${error.message}`); + return { + parse: 1, + jx: 1, + play_parse: true, + parse_type: '壳子超级解析', + parse_source: '芒果TV2', + url: id, + header: JSON.stringify(this.headers) + }; + } + } + + localProxy(param) { + return null; + } +} + +export default new Spider(); \ No newline at end of file diff --git "a/spider/catvod/\351\205\267\351\205\267[\345\256\230].js" "b/spider/catvod/\351\205\267\351\205\267[\345\256\230].js" new file mode 100644 index 00000000..ffdb7289 --- /dev/null +++ "b/spider/catvod/\351\205\267\351\205\267[\345\256\230].js" @@ -0,0 +1,356 @@ +/** + * 优酷视频 - 猫影视/TVBox JS爬虫格式 + * 调用壳子超级解析功能(壳子会自动读取json配置) + @header({ + searchable: 1, + filterable: 1, + quickSearch: 1, + title: '优酷视频', + lang: 'cat' + }) + */ + +class Spider extends BaseSpider { + + constructor() { + super(); + this.host = 'https://www.youku.com'; + this.sessionStore = {}; + + this.headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + 'Referer': 'https://www.youku.com', + 'Accept': 'application/json, text/plain, */*', + 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive' + }; + } + + init(extend = '') { + return ''; + } + + getName() { + return '优酷视频'; + } + + isVideoFormat(url) { + return true; + } + + manualVideoCheck() { + return false; + } + + destroy() { + // 清理资源 + } + + homeContent(filter) { + const categories = '电视剧&电影&综艺&动漫&少儿&纪录片&文化&亲子&教育&搞笑&生活&体育&音乐&游戏'.split('&'); + + const result = { + class: categories.map(name => ({ + type_id: name, + type_name: name + })) + }; + + return result; + } + + homeVideoContent() { + return {list: []}; + } + + async categoryContent(tid, pg, filter, extend) { + try { + const page = parseInt(pg) || 1; + let filterObj = {}; + + if (extend && typeof extend === 'object') { + filterObj = extend; + } + + filterObj.type = tid; + const paramsStr = JSON.stringify(filterObj); + + let url = `https://www.youku.com/category/data?optionRefresh=1&pageNo=${page}¶ms=${encodeURIComponent(paramsStr)}`; + + // 处理session + if (page > 1 && this.sessionStore[tid]) { + url = url.replace("optionRefresh=1", `session=${encodeURIComponent(this.sessionStore[tid])}`); + } + + const response = await this.fetch(url, {}, this.headers); + const resData = response.data; + + if (resData.data && resData.data.filterData && resData.data.filterData.session) { + this.sessionStore[tid] = JSON.stringify(resData.data.filterData.session); + } + + const videos = []; + if (resData.data && resData.data.filterData && Array.isArray(resData.data.filterData.listData)) { + const lists = resData.data.filterData.listData; + for (const it of lists) { + let vid = ""; + if (it.videoLink && it.videoLink.includes("id_")) { + vid = it.videoLink.split("id_")[1].split(".html")[0]; + } else { + vid = "msearch:" + it.title; + } + + videos.push({ + vod_id: vid, + vod_name: it.title || '', + vod_pic: it.img || '', + vod_remarks: it.summary || '', + vod_content: it.subTitle || '' + }); + } + } + + return { + list: videos, + page: page, + pagecount: 9999, + limit: 20, + total: 999999 + }; + + } catch (error) { + console.error(`categoryContent error: ${error.message}`); + return { + list: [], + page: pg, + pagecount: 0, + limit: 20, + total: 0 + }; + } + } + + safeFixYoukuInitialData(rawStr) { + if (!rawStr) return '{}'; + let s = rawStr + .replace(/^[\s\S]*?window\.__INITIAL_DATA__\s*[=:]\s*/, '') + .replace(/;[\s\S]*$/, '') + .replace(/\.{3,}[\s\S]*$/, '') + .replace(/,\s*$/, '') + .trim(); + + if (!s || s.length < 2 || !/^\{/.test(s)) { + return '{}'; + } + + let open = 0, close = 0; + for (let char of s) { + if (char === '{') open++; + if (char === '}') close++; + } + + if (open > close) { + s += '}'.repeat(open - close); + } + if (!s.startsWith('{')) { + s = '{' + s; + } + if (!s.endsWith('}')) { + s += '}'; + } + + return s; + } + + getSafe(obj, path, defaultValue = '') { + if (!obj || typeof obj !== 'object') return defaultValue; + try { + return path.split('.').reduce((o, key) => { + if (o == null) return defaultValue; + return o[key]; + }, obj) ?? defaultValue; + } catch { + return defaultValue; + } + } + + async detailContent(ids) { + try { + const id = ids[0]; + + // 获取剧集列表 + const apiUrl = `https://search.youku.com/api/search?appScene=show_episode&showIds=${id}`; + const apiResponse = await this.fetch(apiUrl, {}, this.headers); + const jsonData = apiResponse.data; + const videoLists = jsonData.serisesList || []; + + // 构建播放列表 + const playUrls = []; + if (videoLists.length > 0) { + for (const item of videoLists) { + const title = item.showVideoStage?.replace("期", "集") || + item.displayName || + item.title || + `第${item.index || '?'}集`; + const url = `https://v.youku.com/v_show/id_${item.videoId}.html`; + playUrls.push(`${title}$${url}`); + } + } + + // 获取详情信息 + let detailInfo = { + title: '', + cover: '', + category: '', + remarks: '', + desc: '' + }; + + try { + const detailUrl = `https://v.youku.com/v_show/id_${id}.html`; + const htmlResponse = await this.fetch(detailUrl, { + headers: { + ...this.headers, + 'Referer': 'https://v.youku.com/' + } + }); + const html = htmlResponse.data; + + // 检查是否触发人机验证 + if (html.includes("人机验证") || html.includes("captcha") || html.includes("verify")) { + detailInfo.desc = "触发优酷人机验证,建议在浏览器中访问优酷官网解除限制后再重试"; + } else if (html.includes("window.__INITIAL_DATA__ =")) { + let dataStr = html.split("window.__INITIAL_DATA__ =")[1]?.split(";")?.[0]?.trim() || '{}'; + dataStr = this.safeFixYoukuInitialData(dataStr); + + try { + const detailJson = JSON.parse(dataStr); + const item = this.getSafe(detailJson, 'moduleList.0.components.0.itemList.0', {}); + const extra = this.getSafe(detailJson, 'pageMap.extra', {}); + + detailInfo.title = item.introTitle || extra.showName || videoLists[0]?.title || ''; + detailInfo.cover = item.showImgV || extra.showImgV || extra.showImg || ''; + detailInfo.category = item.showGenre || extra.videoCategory || ''; + detailInfo.remarks = item.introSubTitle || extra.showSubtitle || item.mark?.text || ''; + } catch (parseErr) { + console.error(`JSON解析失败: ${parseErr.message}`); + } + } else { + detailInfo.title = videoLists[0]?.title?.split(" ")[0] || ''; + } + } catch (detailError) { + console.error(`获取详情失败: ${detailError.message}`); + } + + const vod = { + vod_id: id, + vod_name: detailInfo.title || videoLists[0]?.title || '未知标题', + type_name: detailInfo.category || '', + vod_year: '', + vod_remarks: detailInfo.remarks || '', + vod_content: detailInfo.desc || (detailInfo.remarks ? `简介: ${detailInfo.remarks}` : '暂无简介'), + vod_play_from: playUrls.length > 0 ? '优酷视频' : '', + vod_play_url: playUrls.length > 0 ? playUrls.join('#') : '' + }; + + return {list: [vod]}; + + } catch (error) { + console.error(`detailContent error: ${error.message}`); + return {list: []}; + } + } + + async searchContent(key, quick, pg = '1') { + try { + const page = parseInt(pg) || 1; + const url = `https://search.youku.com/api/search?pg=${page}&keyword=${encodeURIComponent(key)}`; + + const response = await this.fetch(url, {}, this.headers); + const data = response.data; + + const videos = []; + + if (data && Array.isArray(data.pageComponentList)) { + for (const item of data.pageComponentList) { + if (item.commonData) { + const common = item.commonData; + let vid = common.showId || ''; + + if (!vid && common.titleDTO && common.titleDTO.displayName) { + vid = `msearch:${common.titleDTO.displayName}`; + } + + videos.push({ + vod_id: vid, + vod_name: common.titleDTO?.displayName || '', + vod_pic: common.posterDTO?.vThumbUrl || '', + vod_remarks: common.stripeBottom || '', + vod_content: common.updateNotice || '' + }); + } + } + } + + return { + list: videos, + page: page, + pagecount: 9999, + limit: 20, + total: 999999 + }; + + } catch (error) { + console.error(`searchContent error: ${error.message}`); + return { + list: [], + page: pg, + pagecount: 0, + limit: 20, + total: 0 + }; + } + } + + async playerContent(flag, id, vipFlags) { + try { + // 关键:调用壳子超级解析 + // 壳子会自动读取json配置中的解析规则 + const playData = { + parse: 1, // 必须为1,表示需要解析 + jx: 1, // 必须为1,启用解析 + play_parse: true, // 启用播放解析 + parse_type: '壳子超级解析', + parse_source: '优酷视频', + url: id, // 原始优酷链接 + header: JSON.stringify({ + 'User-Agent': this.headers['User-Agent'], + 'Referer': 'https://www.youku.com', + 'Origin': 'https://www.youku.com' + }) + }; + + return playData; + + } catch (error) { + console.error(`playerContent error: ${error.message}`); + // 即使出错也返回超级解析参数,让壳子处理 + return { + parse: 1, + jx: 1, + play_parse: true, + parse_type: '壳子超级解析', + parse_source: '优酷视频', + url: id, + header: JSON.stringify(this.headers) + }; + } + } + + localProxy(param) { + return null; + } +} + +export default new Spider(); \ No newline at end of file From a9be6aa0c219931204278116b766a8bcf33f03fe Mon Sep 17 00:00:00 2001 From: Taois Date: Tue, 20 Jan 2026 22:57:54 +0800 Subject: [PATCH 053/101] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E5=8F=A6?= =?UTF-8?q?=E7=B1=BB=E5=86=99=E6=B3=95=E7=9A=84cat=E6=BA=90=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs_drpy/drpyInject.js | 13 ++++++++++++- .../\345\223\251\345\223\251[\345\256\230].js" | 2 +- .../\345\244\256\345\244\256[\345\256\230].js" | 2 +- .../\345\245\207\345\245\207[\345\256\230].js" | 2 +- .../\346\236\234\346\236\234[\345\256\230].js" | 2 +- .../\351\205\267\351\205\267[\345\256\230].js" | 2 +- 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/libs_drpy/drpyInject.js b/libs_drpy/drpyInject.js index b473ec13..27122610 100644 --- a/libs_drpy/drpyInject.js +++ b/libs_drpy/drpyInject.js @@ -733,11 +733,22 @@ class BaseSpider { this.play = this.playerContent; this.homeVod = this.homeVideoContent; this.proxy = this.localProxy; + // this.fetch = request; } async fetch(url, options) { const content = (await req(url, options)).content; - return {data: content.parseX}; + return { + content, + get data() { // data尝试返回object + try { + // console.log('get data:', this.content); + return this.content.parseX; + } catch (e) { + return {}; + } + } + }; } async homeContent() { diff --git "a/spider/catvod/\345\223\251\345\223\251[\345\256\230].js" "b/spider/catvod/\345\223\251\345\223\251[\345\256\230].js" index df164c9c..91cecaa6 100644 --- "a/spider/catvod/\345\223\251\345\223\251[\345\256\230].js" +++ "b/spider/catvod/\345\223\251\345\223\251[\345\256\230].js" @@ -5,7 +5,7 @@ searchable: 1, filterable: 1, quickSearch: 1, - title: 'B站', + title: '哩哩[官]', lang: 'cat' }) */ diff --git "a/spider/catvod/\345\244\256\345\244\256[\345\256\230].js" "b/spider/catvod/\345\244\256\345\244\256[\345\256\230].js" index 895aea15..478e4b10 100644 --- "a/spider/catvod/\345\244\256\345\244\256[\345\256\230].js" +++ "b/spider/catvod/\345\244\256\345\244\256[\345\256\230].js" @@ -5,7 +5,7 @@ searchable: 1, filterable: 1, quickSearch: 1, - title: '央视大全', + title: '央央[官]', lang: 'cat' }) */ diff --git "a/spider/catvod/\345\245\207\345\245\207[\345\256\230].js" "b/spider/catvod/\345\245\207\345\245\207[\345\256\230].js" index 956ed6b1..89ce8472 100644 --- "a/spider/catvod/\345\245\207\345\245\207[\345\256\230].js" +++ "b/spider/catvod/\345\245\207\345\245\207[\345\256\230].js" @@ -5,7 +5,7 @@ searchable: 1, filterable: 1, quickSearch: 1, - title: '爱奇艺视频', + title: '奇奇[官]', lang: 'cat' }) */ diff --git "a/spider/catvod/\346\236\234\346\236\234[\345\256\230].js" "b/spider/catvod/\346\236\234\346\236\234[\345\256\230].js" index 33f6e159..ea5846fc 100644 --- "a/spider/catvod/\346\236\234\346\236\234[\345\256\230].js" +++ "b/spider/catvod/\346\236\234\346\236\234[\345\256\230].js" @@ -5,7 +5,7 @@ searchable: 1, filterable: 1, quickSearch: 1, - title: '芒果TV', + title: '果果[官]', lang: 'cat' }) */ diff --git "a/spider/catvod/\351\205\267\351\205\267[\345\256\230].js" "b/spider/catvod/\351\205\267\351\205\267[\345\256\230].js" index ffdb7289..754e204f 100644 --- "a/spider/catvod/\351\205\267\351\205\267[\345\256\230].js" +++ "b/spider/catvod/\351\205\267\351\205\267[\345\256\230].js" @@ -5,7 +5,7 @@ searchable: 1, filterable: 1, quickSearch: 1, - title: '优酷视频', + title: '酷酷[官]', lang: 'cat' }) */ From f5b6905c43fa67744347e0ee21966a167d60c42a Mon Sep 17 00:00:00 2001 From: Taois Date: Tue, 20 Jan 2026 23:07:11 +0800 Subject: [PATCH 054/101] =?UTF-8?q?add:=20=E5=A2=9E=E5=8A=A0php=E7=A4=BA?= =?UTF-8?q?=E4=BE=8B=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "spider/php/B\347\253\231.php" | 326 +++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 "spider/php/B\347\253\231.php" diff --git "a/spider/php/B\347\253\231.php" "b/spider/php/B\347\253\231.php" new file mode 100644 index 00000000..902093e0 --- /dev/null +++ "b/spider/php/B\347\253\231.php" @@ -0,0 +1,326 @@ + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36", + "Referer" => "https://www.bilibili.com" + ]; + + public function __construct() { + $this->extendDict = $this->getExtendDict(); + $this->cookie = $this->getCookie(); + } + + private function getExtendDict() { + return [ + 'cookie' => $this->getConfigCookie(), + 'thread' => '0' + ]; + } + + private function getConfigCookie() { + // 配置您的B站Cookie + return 'buvid3=xxxx; SESSDATA=xxxx;'; + } + + private function getCookie() { + $cookie = $this->extendDict['cookie'] ?? ''; + if (empty($cookie)) return []; + + $cookies = []; + $pairs = explode(';', $cookie); + foreach ($pairs as $pair) { + $pair = trim($pair); + if (strpos($pair, '=') !== false) { + list($name, $value) = explode('=', $pair, 2); + $cookies[trim($name)] = trim($value); + } + } + return $cookies; + } + + private function httpRequest($url, $params = []) { + $ch = curl_init(); + + if (!empty($params)) { + $url .= '?' . http_build_query($params); + } + + $headers = []; + foreach ($this->header as $key => $value) { + $headers[] = $key . ': ' . $value; + } + + curl_setopt_array($ch, [ + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 10, + CURLOPT_HTTPHEADER => $headers, + CURLOPT_COOKIE => $this->buildCookieString(), + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_FOLLOWLOCATION => true + ]); + + $response = curl_exec($ch); + curl_close($ch); + + return json_decode($response, true) ?: []; + } + + private function buildCookieString() { + $pairs = []; + foreach ($this->cookie as $name => $value) { + $pairs[] = $name . '=' . $value; + } + return implode('; ', $pairs); + } + + // homeContent - 首页分类 + public function homeContent() { + $classes = [ + ["type_id" => "沙雕仙逆", "type_name" => "傻屌仙逆"], + ["type_id" => "沙雕动画", "type_name" => "沙雕动画"], + ["type_id" => "纪录片超清", "type_name" => "纪录片"], + ["type_id" => "演唱会超清", "type_name" => "演唱会"], + ["type_id" => "音乐超清", "type_name" => "流行音乐"], + ["type_id" => "美食超清", "type_name" => "美食"], + ["type_id" => "食谱", "type_name" => "食谱"], + ["type_id" => "体育超清", "type_name" => "体育"], + ["type_id" => "球星", "type_name" => "球星"], + ["type_id" => "中小学教育", "type_name" => "教育"], + ["type_id" => "幼儿教育", "type_name" => "幼儿教育"], + ["type_id" => "旅游", "type_name" => "旅游"], + ["type_id" => "风景4K", "type_name" => "风景"], + ["type_id" => "说案", "type_name" => "说案"], + ["type_id" => "知名UP主", "type_name" => "知名UP主"], + ["type_id" => "探索发现超清", "type_name" => "探索发现"], + ["type_id" => "鬼畜", "type_name" => "鬼畜"], + ["type_id" => "搞笑超清", "type_name" => "搞笑"], + ["type_id" => "儿童超清", "type_name" => "儿童"], + ["type_id" => "动物世界超清", "type_name" => "动物世界"], + ["type_id" => "相声小品超清", "type_name" => "相声小品"], + ["type_id" => "戏曲", "type_name" => "戏曲"], + ["type_id" => "解说", "type_name" => "解说"], + ["type_id" => "演讲", "type_name" => "演讲"], + ["type_id" => "小姐姐超清", "type_name" => "小姐姐"], + ["type_id" => "荒野求生超清", "type_name" => "荒野求生"], + ["type_id" => "健身", "type_name" => "健身"], + ["type_id" => "帕梅拉", "type_name" => "帕梅拉"], + ["type_id" => "太极拳", "type_name" => "太极拳"], + ["type_id" => "广场舞", "type_name" => "广场舞"], + ["type_id" => "舞蹈", "type_name" => "舞蹈"], + ["type_id" => "音乐", "type_name" => "音乐"], + ["type_id" => "歌曲", "type_name" => "歌曲"], + ["type_id" => "MV4K", "type_name" => "MV"], + ["type_id" => "舞曲超清", "type_name" => "舞曲"], + ["type_id" => "4K", "type_name" => "4K"], + ["type_id" => "电影", "type_name" => "电影"], + ["type_id" => "电视剧", "type_name" => "电视剧"], + ["type_id" => "白噪音超清", "type_name" => "白噪音"], + ["type_id" => "考公考证", "type_name" => "考公考证"], + ["type_id" => "平面设计教学", "type_name" => "平面设计教学"], + ["type_id" => "软件教程", "type_name" => "软件教程"], + ["type_id" => "Windows", "type_name" => "Windows"] + ]; + + return ['class' => $classes]; + } + + // homeVideoContent - 首页推荐视频 + public function homeVideoContent() { + $url = 'https://api.bilibili.com/x/web-interface/popular'; + $data = $this->httpRequest($url, ['ps' => 20, 'pn' => 1]); + + $videos = []; + if (isset($data['data']['list'])) { + foreach ($data['data']['list'] as $item) { + $videos[] = [ + 'vod_id' => $item['aid'], + 'vod_name' => strip_tags($item['title']), + 'vod_pic' => $item['pic'], + 'vod_remarks' => $this->formatDuration($item['duration']) + ]; + } + } + + return ['list' => $videos]; + } + + // categoryContent - 分类内容(使用搜索API) + public function categoryContent($tid, $page, $filters = []) { + $page = max(1, intval($page)); + + $url = 'https://api.bilibili.com/x/web-interface/search/type'; + $params = [ + 'search_type' => 'video', + 'keyword' => $tid, + 'page' => $page + ]; + + $data = $this->httpRequest($url, $params); + + $videos = []; + if (isset($data['data']['result'])) { + foreach ($data['data']['result'] as $item) { + if ($item['type'] !== 'video') continue; + + $videos[] = [ + 'vod_id' => $item['aid'], + 'vod_name' => strip_tags($item['title']), + 'vod_pic' => 'https:' . $item['pic'], + 'vod_remarks' => $this->formatSearchDuration($item['duration']) + ]; + } + } + + $pageCount = $data['data']['numPages'] ?? 1; + $total = $data['data']['numResults'] ?? count($videos); + + return [ + 'list' => $videos, + 'page' => $page, + 'pagecount' => $pageCount, + 'limit' => 20, + 'total' => $total + ]; + } + + // detailContent - 视频详情 + public function detailContent($vid) { + $url = 'https://api.bilibili.com/x/web-interface/view'; + $data = $this->httpRequest($url, ['aid' => $vid]); + + if (!isset($data['data'])) { + return ['list' => []]; + } + + $video = $data['data']; + + // 构建播放列表 + $playUrl = ''; + foreach ($video['pages'] as $index => $page) { + $part = $page['part'] ?: '第' . ($index + 1) . '集'; + $duration = $this->formatDuration($page['duration']); + $playUrl .= "{$part}\${$vid}_{$page['cid']}#"; + } + + $vod = [ + "vod_id" => $vid, + "vod_name" => strip_tags($video['title']), + "vod_pic" => $video['pic'], + "vod_content" => $video['desc'], + "vod_play_from" => "B站视频", + "vod_play_url" => rtrim($playUrl, '#') + ]; + + return ['list' => [$vod]]; + } + + // playContent - 播放地址(高清优化) + public function playContent($vid) { + if (strpos($vid, '_') !== false) { + list($avid, $cid) = explode('_', $vid); + } else { + return $this->errorResponse('无效的视频ID格式'); + } + + // 使用高质量参数 + $url = 'https://api.bilibili.com/x/player/playurl'; + $params = [ + 'avid' => $avid, + 'cid' => $cid, + 'qn' => 112, // 原画质量 + 'fnval' => 0, + ]; + + $data = $this->httpRequest($url, $params); + + if (!isset($data['data']) || $data['code'] !== 0) { + return $this->errorResponse('获取播放地址失败'); + } + + // 直接返回第一个播放地址 + if (isset($data['data']['durl'][0]['url'])) { + $playUrl = $data['data']['durl'][0]['url']; + + $headers = $this->header; + $headers['Referer'] = 'https://www.bilibili.com/video/av' . $avid; + $headers['Origin'] = 'https://www.bilibili.com'; + + return [ + 'parse' => 0, + 'url' => $playUrl, + 'header' => $headers, + 'danmaku' => "https://api.bilibili.com/x/v1/dm/list.so?oid={$cid}" + ]; + } + + return $this->errorResponse('无法获取播放地址'); + } + + // 工具函数 + private function formatDuration($seconds) { + if ($seconds <= 0) return '00:00'; + $minutes = floor($seconds / 60); + $secs = $seconds % 60; + return sprintf('%02d:%02d', $minutes, $secs); + } + + private function formatSearchDuration($duration) { + $parts = explode(':', $duration); + if (count($parts) === 2) { + return $duration; + } + return '00:00'; + } + + private function errorResponse($message) { + return [ + 'parse' => 0, + 'url' => '', + 'error' => $message + ]; + } +} + +// 主处理逻辑 +$ac = $_GET['ac'] ?? 'detail'; +$t = $_GET['t'] ?? ''; +$pg = $_GET['pg'] ?? '1'; +$f = $_GET['f'] ?? ''; +$ids = $_GET['ids'] ?? ''; +$id = $_GET['id'] ?? ''; + +$spider = new BiliBiliSpider(); + +try { + switch ($ac) { + case 'detail': + if (!empty($ids)) { + echo json_encode($spider->detailContent($ids)); + } elseif (!empty($t)) { + $filters = !empty($f) ? json_decode($f, true) : []; + echo json_encode($spider->categoryContent($t, $pg, $filters)); + } else { + $result = $spider->homeContent(); + $videoResult = $spider->homeVideoContent(); + $result['list'] = $videoResult['list']; + echo json_encode($result); + } + break; + + case 'play': + echo json_encode($spider->playContent($id)); + break; + + default: + echo json_encode(['error' => '未知操作: ' . $ac]); + } +} catch (Exception $e) { + echo json_encode(['error' => $e->getMessage()]); +} +?> From bcd8939bfba1b44dee3299713e155d415e8bfe1e Mon Sep 17 00:00:00 2001 From: Taois Date: Tue, 20 Jan 2026 23:32:16 +0800 Subject: [PATCH 055/101] =?UTF-8?q?add:=20=E5=A2=9E=E5=8A=A0php=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spider/php/config.php | 46 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 spider/php/config.php diff --git a/spider/php/config.php b/spider/php/config.php new file mode 100644 index 00000000..d8327c65 --- /dev/null +++ b/spider/php/config.php @@ -0,0 +1,46 @@ + "php_" . $filename, + "name" => $filename . "(PHP)", + "type" => 4, + "api" => "http://127.0.0.1:9980/" . $filename . ".php", + "searchable" => 1, + "quickSearch" => 1, + "changeable" => 0 + ]; +} + +// 输出 JSON +echo json_encode( + ["sites" => $sites], + JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT +); From 6d69335db1cec97a306827a889452c49a1238c88 Mon Sep 17 00:00:00 2001 From: Taois Date: Tue, 20 Jan 2026 23:41:27 +0800 Subject: [PATCH 056/101] =?UTF-8?q?add:=20=E5=A2=9E=E5=8A=A0php=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spider/php/config.php | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/spider/php/config.php b/spider/php/config.php index d8327c65..052cfc2a 100644 --- a/spider/php/config.php +++ b/spider/php/config.php @@ -1,31 +1,24 @@ $sites], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT From d39a76e6f936c013ed2330145080408b3fbaa996 Mon Sep 17 00:00:00 2001 From: Taois Date: Wed, 21 Jan 2026 10:12:51 +0800 Subject: [PATCH 057/101] =?UTF-8?q?docs:=E5=A2=9E=E5=8A=A0=E8=B6=85?= =?UTF-8?q?=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + public/index.html | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 3cbdcc29..f8488af2 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ nodejs作为服务端的drpy实现。全面升级异步写法 * [猫源调试教程](/docs/catDebug.md) * [接口压测教程](/docs/httpTest.md) * [AI编程工具 trae](https://www.trae.ai/account-setting#subscription) | 邮编ZIP输入: 518000 +* [推荐使用AI模型-GLM4.7](https://www.bigmodel.cn/glm-coding?ic=DRV3C8M5NX) | [GLM配置文档](https://docs.bigmodel.cn/cn/coding-plan/tool/trae) * [免费AI-360纳米](https://bot.n.cn/)|[免费AI-当贝AI](https://ai.dangbei.com/chat)|[国外聚合全模型](https://lmarena.ai/) * [本站防止爬虫协议](/robots.txt) * [油猴脚本-反切屏检测](/public/monkey/check_screen_leave.user.js) diff --git a/public/index.html b/public/index.html index 83d6552e..41ed026e 100644 --- a/public/index.html +++ b/public/index.html @@ -25,6 +25,7 @@

常用超链接

  • 猫源调试教程
  • 接口压测教程
  • AI编程工具 trae | 邮编ZIP输入: 518000
  • +
  • 推荐使用AI模型-GLM4.7 | GLM配置文档
  • 免费AI-360纳米|免费AI-当贝AI|国外聚合全模型
  • 本站防止爬虫协议
  • 油猴脚本-反切屏检测
  • From 6e6d6041fe3c6a8f6e4d9417ae6d90be05e97827 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Wed, 21 Jan 2026 14:44:28 +0800 Subject: [PATCH 058/101] =?UTF-8?q?Update=20=E6=A2=A8=E5=9B=AD=E8=A1=8C[?= =?UTF-8?q?=E6=88=8F].js=20and=20add=20new=20js=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\346\234\250\345\205\256[\344\274\230].js" | 14 +- ...\345\233\255\350\241\214[\346\210\217].js" | 261 ++++++++++++++++++ ...\351\237\263\344\271\220[\345\220\254].js" | 14 + ...\351\237\263\344\271\220[\345\220\254].js" | 49 +--- 4 files changed, 289 insertions(+), 49 deletions(-) rename "spider/js_bad/\346\234\250\345\205\256[\344\274\230].js" => "spider/js/\346\234\250\345\205\256[\344\274\230].js" (88%) create mode 100644 "spider/js/\346\242\250\345\233\255\350\241\214[\346\210\217].js" create mode 100644 "spider/js/\347\210\261\347\216\251\351\237\263\344\271\220[\345\220\254].js" diff --git "a/spider/js_bad/\346\234\250\345\205\256[\344\274\230].js" "b/spider/js/\346\234\250\345\205\256[\344\274\230].js" similarity index 88% rename from "spider/js_bad/\346\234\250\345\205\256[\344\274\230].js" rename to "spider/js/\346\234\250\345\205\256[\344\274\230].js" index 918c35da..59cac191 100644 --- "a/spider/js_bad/\346\234\250\345\205\256[\344\274\230].js" +++ "b/spider/js/\346\234\250\345\205\256[\344\274\230].js" @@ -20,7 +20,19 @@ var rule = { quickSearch: 1, filterable: 0, headers: { - 'User-Agent': MOBILE_UA + 'User-Agent': MOBILE_UA, + 'Accept': 'application/json, text/plain, */*', + 'accept-language': 'zh-CN,zh;q=0.9', + 'cache-control': 'no-cache', + 'pragma': 'no-cache', + 'priority': 'u=1, i', + 'sec-ch-ua': '"Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="24"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'sec-fetch-dest': 'empty', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'same-origin', + 'x-platform': 'web' }, play_parse: true, search_match: true, diff --git "a/spider/js/\346\242\250\345\233\255\350\241\214[\346\210\217].js" "b/spider/js/\346\242\250\345\233\255\350\241\214[\346\210\217].js" new file mode 100644 index 00000000..22af9d45 --- /dev/null +++ "b/spider/js/\346\242\250\345\233\255\350\241\214[\346\210\217].js" @@ -0,0 +1,261 @@ +/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 0, + title: '梨园行戏曲', + author: 'EylinSir', + '类型': '影视', + logo: 'https://img.znds.com//uploads/new/221222/9-2212221050561N.png', + lang: 'ds' +}) +*/ + +var rule = { + 类型: '影视', + author: 'EylinSir', + title: '梨园行戏曲', + desc: '梨园行戏曲源', + host: 'https://fly.daoran.tv', + homeUrl: 'https://fly.daoran.tv', + url: '/API_ROP/search/album/screen', + searchUrl: '/API_ROP/search/album/list?keyword=**', + logo: 'https://img.znds.com//uploads/new/221222/9-2212221050561N.png', + searchable: 1, + quickSearch: 0, + filterable: 1, + timeout: 10000, + play_parse: true, + headers: { + 'md5': 'SkvyrWqK9QHTdCT12Rhxunjx+WwMTe9y4KwgeASFDhbYabRSPskR0Q==', + 'Content-Type': 'application/json; charset=UTF-8', + 'User-Agent': 'okhttp/3.12.10', + 'Host': 'fly.daoran.tv', + 'Connection': 'Keep-Alive' + }, + + request: async function (url, obj) { + obj = obj || {}; + let response = await _fetch(url, { + method: obj.method || 'POST', + headers: obj.headers || this.headers, + body: obj.data ? JSON.stringify(obj.data) : undefined + }); + return response.text(); + }, + + _format_img: function (img) { + if (!img) { + return ''; + } + if (!img.startsWith('http')) { + return `https://ottphoto.daoran.tv/HD/${img}`; + } + return img; + }, + + 预处理: async function () {}, + + class_parse: async function () { + let cate_list = [ + {"n": "全部", "v": ""}, + {"n": "黄梅戏", "v": "hmx"}, {"n": "京剧", "v": "jingju"}, {"n": "曲剧", "v": "quju"}, + {"n": "秦腔", "v": "qinq"}, {"n": "潮剧", "v": "chaoju"}, {"n": "沪剧", "v": "huju"}, + {"n": "昆曲", "v": "kunqu"}, {"n": "淮剧", "v": "huaiju"}, {"n": "婺剧", "v": "wuju"}, + {"n": "河南大鼓书", "v": "hndgs"}, {"n": "滇剧", "v": "dianju"}, {"n": "老年大学", "v": "WK"}, + {"n": "绍剧", "v": "shaojv"}, {"n": "曲艺晚会", "v": "else"}, {"n": "皮影戏", "v": "pyx"}, + {"n": "四平调", "v": "spd"}, {"n": "吕剧", "v": "lvjv"}, {"n": "柳琴戏", "v": "liuqx"}, + {"n": "莆仙戏", "v": "pxx"}, {"n": "宛梆", "v": "wb"}, {"n": "锡剧", "v": "xiju"}, + {"n": "大平调", "v": "dpd"}, {"n": "话剧", "v": "huaju"}, {"n": "西秦戏", "v": "xqx"}, + {"n": "川剧", "v": "chuanju"}, {"n": "赣剧", "v": "tagId"}, {"n": "太康道情", "v": "tkdq"}, + {"n": "闽剧", "v": "minju"}, {"n": "梅花大鼓", "v": "mhdg"}, {"n": "吉剧", "v": "jiju"}, + {"n": "白字戏", "v": "bzx"}, {"n": "豫剧", "v": "yuju"}, {"n": "越剧", "v": "yueju"}, + {"n": "评剧", "v": "pingju"}, {"n": "坠子", "v": "hnzz"}, {"n": "河北梆子", "v": "hbbz"}, + {"n": "粤剧", "v": "gddx"}, {"n": "二夹弦", "v": "ejx"}, {"n": "河南琴书", "v": "hnqs"}, + {"n": "戏曲", "v": "xq"}, {"n": "二人台", "v": "ERT"}, {"n": "越调", "v": "yued"}, + {"n": "乐腔", "v": "lq"}, {"n": "扬剧", "v": "yangju"}, {"n": "京韵大鼓", "v": "jydg"}, + {"n": "彩调", "v": "caidiao"}, {"n": "琼剧", "v": "qiongju"}, {"n": "蒲剧", "v": "pujv"}, + {"n": "西河大鼓", "v": "xhdg"}, {"n": "湘剧", "v": "xj"}, {"n": "麦田乡韾", "v": "mtxy"}, + {"n": "评书", "v": "pingshu"}, {"n": "庐剧", "v": "luju"}, {"n": "单弦", "v": "danxian"}, + {"n": "花鼓戏", "v": "huagx"}, {"n": "相声", "v": "xiang"}, {"n": "四股弦", "v": "sgx"}, + {"n": "保定老调", "v": "bdld"}, {"n": "晋剧", "v": "jinju"}, {"n": "其他", "v": "other"}, + {"n": "正字戏", "v": "zzx"}, {"n": "楚剧", "v": "chuju"} + ]; + + return { + class: [{ 'type_name': '戏曲片库', 'type_id': 'all' }], + filters: { + "all": [ + {"key": "sect", "name": "曲种", "value": cate_list}, + {"key": "area", "name": "资费", "value": [{"n": "全部", "v": "0"}, {"n": "免费", "v": "1"}, {"n": "VIP", "v": "2"}]}, + {"key": "sort", "name": "排序", "value": [{"n": "最热", "v": "hot"}, {"n": "最新", "v": "online"}]} + ] + } + }; + }, + + 推荐: async function () { + return await this.一级('all', 1, {}, {}); + }, + + 一级: async function (tid, pg, filter, extend) { + let url = `${this.host}/API_ROP/search/album/screen`; + let sect = extend?.sect || ''; + if (tid === 'all' && !sect) { + sect = ''; + } + + let payload = { + "cur": parseInt(pg), + "pageSize": 30, + "resType": 1, + "sect": sect, + "orderby": extend?.sort || 'hot', + "tagId": 0, + "userId": "92315ec6e58a45ba7f47fd143b3d7956", + "channel": "vivo", + "item": "y9", + "nodeCode": "001000", + "project": "lyhxcx" + }; + + let area = extend?.area || '0'; + if (area === '1' || area === '2') { + payload['free'] = parseInt(area); + } + + try { + let resp = await this.request(url, { data: payload }); + let json = JSON.parse(resp); + let data = json.pb || json.data || {}; + let vod_list = []; + for (let item of data.dataList || []) { + vod_list.push({ + title: item.name, + url: `${this.host}/API_ROP/album/res/list?albumCode=${item.code}`, + desc: (item.publishTime || '').split(' ')[0], + pic_url: this._format_img(item.imgsec), + vod_year: (item.publishTime || '').substring(0, 4) + }); + } + + return setResult(vod_list); + } catch (e) { + console.error(e); + return setResult([]); + } + }, + + 二级: async function () { + let albumCode = this.input.match(/albumCode=(.*?)(?:&|$)/)[1]; + let url = `${this.host}/API_ROP/album/res/list`; + + let payload = { + "albumCode": albumCode, + "cur": 1, + "pageSize": 500, + "userId": "92315ec6e58a45ba7f47fd143b3d7956", + "channel": "vivo", + "item": "y9", + "nodeCode": "001000", + "project": "lyhxcx" + }; + + try { + let resp = await this.request(url, { data: payload }); + let json = JSON.parse(resp); + let album = json.album || {}; + let tracks = json.pb?.dataList || []; + tracks.sort((a, b) => parseInt(a.sort || 0) - parseInt(b.sort || 0)); + let play_urls = []; + for (let t of tracks) { + if (t.code) { + play_urls.push(`${t.name.replace(/\$/g, '_')}$${t.code}`); + } + } + + let VOD = { + vod_id: albumCode, + vod_name: album.name || '未知', + vod_pic: this._format_img(album.imgsec), + type_name: "戏曲", + vod_year: album.publishTime || '', + vod_area: "中国", + vod_content: album.des || '暂无简介', + vod_play_from: "梨园行", + vod_play_url: play_urls.join('#') + }; + + return VOD; + } catch (e) { + console.error(e); + return {}; + } + }, + + 搜索: async function () { + let url = `${this.host}/API_ROP/search/album/list`; + let payload = { + "cur": parseInt(this.MY_PAGE), + "pageSize": 20, + "keyword": this.KEY, + "item": "y9", + "nodeCode": "001000", + "orderby": "hot", + "px": 2, + "sect": [], + "userId": "92315ec6e58a45ba7f47fd143b3d7956", + "project": "lyhxcx" + }; + + try { + let resp = await this.request(url, { data: payload }); + let json = JSON.parse(resp); + let data = json.pb || json.data || {}; + let vod_list = []; + for (let item of data.dataList || []) { + vod_list.push({ + title: item.name, + url: `${this.host}/API_ROP/album/res/list?albumCode=${item.code}`, + desc: (item.publishTime || ''), + pic_url: this._format_img(item.imgsec) + }); + } + return setResult(vod_list); + } catch (e) { + console.error(e); + return setResult([]); + } + }, + + lazy: async function () { + let resCode = this.input; + let url = `${this.host}/API_ROP/play/get/playurl`; + let payload = { + "resCode": resCode, + "item": "y9", + "mask": 0, + "nodeCode": "001000", + "project": "lyhxcx", + "px": 2, + "userId": "92315ec6e58a45ba7f47fd143b3d7956" + }; + + try { + let resp = await this.request(url, { data: payload }); + let json = JSON.parse(resp); + let play_url = json.playres?.playurl || ''; + return { + parse: 0, + url: play_url, + header: { 'User-Agent': this.headers['User-Agent'] } + }; + } catch (e) { + console.error(e); + return { + parse: 0, + url: '' + }; + } + } +}; \ No newline at end of file diff --git "a/spider/js/\347\210\261\347\216\251\351\237\263\344\271\220[\345\220\254].js" "b/spider/js/\347\210\261\347\216\251\351\237\263\344\271\220[\345\220\254].js" new file mode 100644 index 00000000..28c15f7c --- /dev/null +++ "b/spider/js/\347\210\261\347\216\251\351\237\263\344\271\220[\345\220\254].js" @@ -0,0 +1,14 @@ +/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 1, + title: '爱玩音乐', + author: 'EylinSir', + '类型': '音乐', + logo: 'https://www.22a5.com/favicon.ico', + lang: 'ds' +}) +*/ + +dmFyIHJ1bGUgPSB7CiAgICDnsbvlnos6ICfpn7PkuZAnLAogICAgdGl0bGU6ICfniLHnjqnpn7PkuZAnLAogICAgYXV0aG9yOiAnRXlsaW5TaXInLAogICAgaG9zdDogJ2h0dHBzOi8vd3d3LjIyYTUuY29tJywKICAgIHVybDogJy9meWNsYXNzL2Z5ZmlsdGVyLWZ5cGFnZS8nLAogICAgbG9nbzogJ2h0dHBzOi8vd3d3LjIyYTUuY29tL2Zhdmljb24uaWNvJywKICAgIGNsYXNzX25hbWU6ICfnlLXlj7Am5q2M5Y2VJuS4k+i+kSbmrYzmiYsm6auY5riFTVYm5paw5q2M5qacJlRPUOamnOWNlScsCiAgICBjbGFzc191cmw6ICcvcmFkaW9saXN0L2luZGV4Lmh0bWwmL3BsYXl0eXBlL2luZGV4Lmh0bWwmL2FsYnVtbGlzdC9pbmRleC5odG1sJi9zaW5nZXJsaXN0L2luZGV4L2luZGV4L2luZGV4L2luZGV4Lmh0bWwmL212bGlzdC9odWF5dS5odG1sJi9saXN0L25ldy5odG1sJi9saXN0L3RvcC5odG1sJywKICAgIHNlYXJjaFVybDogJy9zby8qKi9meXBhZ2UuaHRtbCcsCiAgICBzZWFyY2hhYmxlOiAxLAogICAgcXVpY2tTZWFyY2g6IDEsCiAgICBmaWx0ZXJhYmxlOiAxLAogICAgdGltZW91dDogNTAwMCwKICAgIHBsYXlfcGFyc2U6IHRydWUsCiAgICBoZWFkZXJzOiB7CiAgICAgICAgJ1VzZXItQWdlbnQnOiBNT0JJTEVfVUEsCiAgICAgICAgJ1JlZmVyZXInOiAnaHR0cHM6Ly93d3cuMjJhNS5jb20vJwogICAgfSwKICAgIGZpbHRlcjogewogICAgICAgICIvcmFkaW9saXN0L2luZGV4Lmh0bWwiOiBbeyBrZXk6ICJpZCIsIG5hbWU6ICLliIbnsbsiLCB2YWx1ZTogW3sgIm4iOiAi5pyA5pawIiwgInYiOiAiaW5kZXgiIH0sIHsgIm4iOiAi5pyA54OtIiwgInYiOiAiaG90IiB9LCB7ICJuIjogIuacieWjsOWwj+ivtCIsICJ2IjogIm5vdmVsIiB9LCB7ICJuIjogIuebuOWjsCIsICJ2IjogInhpYW5neWkiIH0sIHsgIm4iOiAi6Z+z5LmQIiwgInYiOiAibXVzaWMiIH0sIHsgIm4iOiAi5oOF5oSfIiwgInYiOiAiZW1vdGlvbiIgfSwgeyAibiI6ICLlm73mvKsiLCAidiI6ICJnYW1lIiB9LCB7ICJuIjogIuW9seinhiIsICJ2IjogInlpbmdzaGkiIH0sIHsgIm4iOiAi6ISx5Y+j56eAIiwgInYiOiAidGFsa3Nob3ciIH0sIHsgIm4iOiAi5Y6G5Y+yIiwgInYiOiAiaGlzdG9yeSIgfSwgeyAibiI6ICLlhL/nq6UiLCAidiI6ICJjaGlsZHJlbiIgfSwgeyAibiI6ICLmlZnogrIiLCAidiI6ICJlZHVjYXRpb24iIH0sIHsgIm4iOiAi5YWr5Y2mIiwgInYiOiAiZ29zc2lwIiB9LCB7ICJuIjogIuaOqOeQhiIsICJ2IjogInR1aWxpIiB9LCB7ICJuIjogIuWktOadoSIsICJ2IjogImhlYWRsaW5lIiB9XSB9XSwKICAgICAgICAiL3Npbmdlcmxpc3QvaW5kZXgvaW5kZXgvaW5kZXgvaW5kZXguaHRtbCI6IFsKICAgICAgICAgICAgeyAia2V5IjogImFyZWEiLCAibmFtZSI6ICLlnLDljLoiLCAidmFsdWUiOiBbeyAibiI6ICLlhajpg6giLCAidiI6ICJpbmRleCIgfSwgeyAibiI6ICLljY7or60iLCAidiI6ICJodWF5dSIgfSwgeyAibiI6ICLmrKfnvo4iLCAidiI6ICJvdW1laSIgfSwgeyAibiI6ICLpn6nlm70iLCAidiI6ICJoYW5ndW8iIH0sIHsgIm4iOiAi5pel5pysIiwgInYiOiAicmlicm4iIH1dIH0sCiAgICAgICAgICAgIHsgImtleSI6ICJzZXgiLCAibmFtZSI6ICLmgKfliKsiLCAidmFsdWUiOiBbeyAibiI6ICLlhajpg6giLCAidiI6ICJpbmRleCIgfSwgeyAibiI6ICLnlLciLCAidiI6ICJtYWxlIiB9LCB7ICJuIjogIuWlsyIsICJ2IjogImdpcmwiIH0sIHsgIm4iOiAi57uE5ZCIIiwgInYiOiAiYmFuZCIgfV0gfSwKICAgICAgICAgICAgeyAia2V5IjogImdlbnJlIiwgIm5hbWUiOiAi5rWB5rS+IiwgInZhbHVlIjogW3sgIm4iOiAi5YWo6YOoIiwgInYiOiAiaW5kZXgiIH0sIHsgIm4iOiAi5rWB6KGMIiwgInYiOiAibGl1eGluZyIgfSwgeyAibiI6ICLnlLXlrZAiLCAidiI6ICJkaWFuemkiIH0sIHsgIm4iOiAi5pGH5ruaIiwgInYiOiAieWFvZ3VuIiB9LCB7ICJuIjogIuWYu+WTiCIsICJ2IjogInhpaGEiIH0sIHsgIm4iOiAiUiZCIiwgInYiOiAicmIiIH0sIHsgIm4iOiAi5rCR6LCjIiwgInYiOiAibWlueWFvIiB9LCB7ICJuIjogIueIteWjqyIsICJ2IjogImp1ZXNoaSIgfSwgeyAibiI6ICLlj6TlhbgiLCAidiI6ICJndWRpYW4iIH1dIH0sCiAgICAgICAgICAgIHsgImtleSI6ICJjaGFyIiwgIm5hbWUiOiAi5a2X5q+NIiwgInZhbHVlIjogW3sgIm4iOiAi5YWo6YOoIiwgInYiOiAiaW5kZXgiIH0sIHsgIm4iOiAiQSIsICJ2IjogImEiIH0sIHsgIm4iOiAiQiIsICJ2IjogImIiIH0sIHsgIm4iOiAiQyIsICJ2IjogImMiIH0sIHsgIm4iOiAiRCIsICJ2IjogImQiIH0sIHsgIm4iOiAiRSIsICJ2IjogImUiIH0sIHsgIm4iOiAiRiIsICJ2IjogImYiIH0sIHsgIm4iOiAiRyIsICJ2IjogImciIH0sIHsgIm4iOiAiSCIsICJ2IjogImgiIH0sIHsgIm4iOiAiSSIsICJ2IjogImkiIH0sIHsgIm4iOiAiSiIsICJ2IjogImoiIH0sIHsgIm4iOiAiSyIsICJ2IjogImsiIH0sIHsgIm4iOiAiTCIsICJ2IjogImwiIH0sIHsgIm4iOiAiTSIsICJ2IjogIm0iIH0sIHsgIm4iOiAiTiIsICJ2IjogIm4iIH0sIHsgIm4iOiAiTyIsICJ2IjogIm8iIH0sIHsgIm4iOiAiUCIsICJ2IjogInAiIH0sIHsgIm4iOiAiUSIsICJ2IjogInEiIH0sIHsgIm4iOiAiUiIsICJ2IjogInIiIH0sIHsgIm4iOiAiUyIsICJ2IjogInMiIH0sIHsgIm4iOiAiVCIsICJ2IjogInQiIH0sIHsgIm4iOiAiVSIsICJ2IjogInUiIH0sIHsgIm4iOiAiViIsICJ2IjogInYiIH0sIHsgIm4iOiAiVyIsICJ2IjogInciIH0sIHsgIm4iOiAiWCIsICJ2IjogIngiIH0sIHsgIm4iOiAiWSIsICJ2IjogInkiIH0sIHsgIm4iOiAiWiIsICJ2IjogInoiIH1dIH0KICAgICAgICBdLAogICAgICAgICIvbXZsaXN0L2h1YXl1Lmh0bWwiOiBbeyAia2V5IjogImlkIiwgIm5hbWUiOiAi57G75Z6LIiwgInZhbHVlIjogW3sgIm4iOiAi5Y2O6K+t57K+6YCJIiwgInYiOiAiaHVheXUiIH0sIHsgIm4iOiAi5pel6Z+p57K+6YCJIiwgInYiOiAiIHJpaGFuIiB9LCB7ICJuIjogIuasp+e+jueyvumAiSIsICJ2IjogIm91bWVpIiB9XSB9XQogICAgfSwKCiAgICBfYWJzOiAodXJsKSA9PiB7CiAgICAgICAgaWYgKCF1cmwgfHwgdHlwZW9mIHVybCAhPT0gJ3N0cmluZycpIHJldHVybiAnJzsKICAgICAgICByZXR1cm4gdXJsLnN0YXJ0c1dpdGgoJ2h0dHAnKSA/IHVybCA6IGBodHRwczovL3d3dy4yMmE1LmNvbSR7dXJsLnN0YXJ0c1dpdGgoJy8nKSA/IHVybCA6ICcvJyArIHVybH1gOwogICAgfSwKCiAgICBfY2xlYW46ICh0ZXh0KSA9PiAodGV4dCB8fCAnJykucmVwbGFjZSgvKOeIseeOqemfs+S5kOe9kXzop4bpopHkuIvovb3or7TmmI586KeG6aKR5LiL6L295Zyw5Z2AfHd3d1wuMnQ1OFwuY29tfE1QM+WFjei0ueS4i+i9vXxMUkPmrYzor43kuIvovb185YWo6YOo5q2M5puyfFxb56ysXGQr6aG1XF185Yi35pawfOavj+aXpeaOqOiNkHzmnIDmlrB854Ot6ZeofOaOqOiNkHxNVnzpq5jmuIV85peg5o2fKS9naSwgJycpLnRyaW0oKSwKCiAgICBfZ2V0X2l0ZW1zOiBmdW5jdGlvbihodG1sLCBwZGZhLCBwZCwgcGRmaCkgewogICAgICAgIGlmICh0eXBlb2YgaHRtbCAhPT0gJ3N0cmluZycpIHJldHVybiBbXTsKICAgICAgICBjb25zdCBzZWxlY3RvcnMgPSBbJy52aWRlb19saXN0IGxpJywgJy5wbGF5X2xpc3QgbGknLCAnLnBpY19saXN0IGxpJywgJy5zaW5nZXJfbGlzdCBsaScsICcuYWxpIGxpJywgJy5sYXl1aS1yb3cgbGknLCAnLmJhc2VfbCBsaScsICcubGlzdCBsaScsICcuaXRlbSBsaSddOwogICAgICAgIGxldCBpdGVtcyA9IFtdOwogICAgICAgIGZvciAobGV0IHNlbCBvZiBzZWxlY3RvcnMpIHsKICAgICAgICAgICAgbGV0IGxpc3QgPSBwZGZhKGh0bWwsIHNlbCkgfHwgW107CiAgICAgICAgICAgIGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkgY29udGludWU7CiAgICAgICAgICAgIGZvciAobGV0IGl0IG9mIGxpc3QpIHsKICAgICAgICAgICAgICAgIGxldCBocmVmID0gcGQoaXQsICdhJiZocmVmJyk7CiAgICAgICAgICAgICAgICBpZiAoIWhyZWYgfHwgaHJlZiA9PT0gJy8nIHx8IC8oXC91c2VyXC98XC9sb2dpblwvfGphdmFzY3JpcHQpLy50ZXN0KGhyZWYpKSBjb250aW51ZTsKICAgICAgICAgICAgICAgIGxldCB0aXRsZSA9IHRoaXMuX2NsZWFuKHBkZmgoaXQsICcubmFtZSYmVGV4dCcpIHx8IHBkKGl0LCAnYSYmdGl0bGUnKSB8fCBwZChpdCwgJ2EmJlRleHQnKSk7CiAgICAgICAgICAgICAgICBpZiAoIXRpdGxlKSBjb250aW51ZTsKICAgICAgICAgICAgICAgIGxldCBpbWdfc3JjID0gcGQoaXQsICdpbWcmJmRhdGEtb3JpZ2luYWwnKSB8fCBwZChpdCwgJ2ltZyYmZGF0YS1zcmMnKSB8fCBwZChpdCwgJ2ltZyYmc3JjJyk7CiAgICAgICAgICAgICAgICBsZXQgcGljX3VybCA9IHRoaXMuX2FicygoaW1nX3NyYyB8fCAnJykucmVwbGFjZSgnMTIwJywgJzUwMCcpKTsKICAgICAgICAgICAgICAgIGl0ZW1zLnB1c2goewogICAgICAgICAgICAgICAgICAgIHRpdGxlOiB0aXRsZSwKICAgICAgICAgICAgICAgICAgICB1cmw6IHRoaXMuX2FicyhocmVmKSwKICAgICAgICAgICAgICAgICAgICBwaWNfdXJsOiBwaWNfdXJsLAogICAgICAgICAgICAgICAgICAgIGRlc2M6ICcnCiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gaXRlbXM7CiAgICB9LAoKICAgIOaOqOiNkDogYXN5bmMgZnVuY3Rpb24oKSB7CiAgICAgICAgcmV0dXJuIFtdOwogICAgfSwKCiAgICDkuIDnuqc6IGFzeW5jIGZ1bmN0aW9uKHRpZCwgcGcsIGZpbHRlciwgZXh0ZW5kKSB7CiAgICAgICAgbGV0IHBhZ2UgPSBwZyB8fCAxOwogICAgICAgIGxldCB1cmwgPSB0aWQucmVwbGFjZSgvXC9cLy9nLCAnLycpLnJlcGxhY2UoJy9meWZpbHRlci0xLycsICcnKTsKICAgICAgICBpZiAoL1wvc2luZ2VybGlzdFwvLy50ZXN0KHRpZCkpIHsKICAgICAgICAgICAgbGV0IHAgPSB0aWQuc3BsaXQoJy8nKTsKICAgICAgICAgICAgaWYgKHAubGVuZ3RoID49IDIpIHsKICAgICAgICAgICAgICAgIGxldCBhcmVhID0gZXh0ZW5kLmFyZWEgfHwgcFsyXSB8fCAnaW5kZXgnOwogICAgICAgICAgICAgICAgbGV0IHNleCA9IGV4dGVuZC5zZXggfHwgcFszXSB8fCAnaW5kZXgnOwogICAgICAgICAgICAgICAgbGV0IGdlbnJlID0gZXh0ZW5kLmdlbnJlIHx8IHBbNF0gfHwgJ2luZGV4JzsKICAgICAgICAgICAgICAgIGxldCBjaGFyID0gZXh0ZW5kLmNoYXIgfHwgJ2luZGV4JzsKICAgICAgICAgICAgICAgIHVybCA9IGAvJHtwWzFdfS8ke2FyZWF9LyR7c2V4fS8ke2dlbnJlfS8ke2NoYXJ9Lmh0bWxgOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBpZiAoZXh0ZW5kLmlkICYmICFbJ2luZGV4JywgJ3RvcCddLmluY2x1ZGVzKGV4dGVuZC5pZCkpIHsKICAgICAgICAgICAgdXJsID0gdXJsLnJlcGxhY2UoLyhcdyspXC5odG1sJC8sIGV4dGVuZC5pZCArICcuaHRtbCcpOwogICAgICAgIH0KCiAgICAgICAgaWYgKHBhZ2UgPiAxKSB7CiAgICAgICAgICAgIGxldCBzZXAgPSAvKFwvc2luZ2VybGlzdFwvfFwvcmFkaW9saXN0XC98XC9tdmxpc3RcL3xcL3BsYXl0eXBlXC98XC9saXN0XC8pLy50ZXN0KHVybCkgPyAnLycgOiAnXyc7CiAgICAgICAgICAgIHVybCA9IHVybC5yZXBsYWNlKC8oX1xkK3xcL1xkKyk/XC5odG1sJC8sIGAke3NlcH0ke3BhZ2V9Lmh0bWxgKTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgbGV0IGZpbmFsVXJsID0gdGhpcy5fYWJzKHVybCk7CiAgICAgICAgbGV0IHJlc3BvbnNlID0gYXdhaXQgcmVxKGZpbmFsVXJsKTsKICAgICAgICByZXR1cm4gc2V0UmVzdWx0KHRoaXMuX2dldF9pdGVtcyhyZXNwb25zZS5jb250ZW50IHx8IHJlc3BvbnNlLCB0aGlzLnBkZmEsIHRoaXMucGQsIHRoaXMucGRmaCkpOwogICAgfSwKCiAgICDmkJzntKI6IGFzeW5jIGZ1bmN0aW9uKHdkLCBxdWljaywgcGcpIHsKICAgICAgICBsZXQgcGFnZSA9IHBnIHx8IDE7CiAgICAgICAgbGV0IHVybCA9IHRoaXMuX2FicyhgL3NvLyR7ZW5jb2RlVVJJQ29tcG9uZW50KHdkKX0vJHtwYWdlfS5odG1sYCk7CiAgICAgICAgbGV0IHJlc3BvbnNlID0gYXdhaXQgcmVxKHVybCk7CiAgICAgICAgcmV0dXJuIHNldFJlc3VsdCh0aGlzLl9nZXRfaXRlbXMocmVzcG9uc2UuY29udGVudCB8fCByZXNwb25zZSwgdGhpcy5wZGZhLCB0aGlzLnBkLCB0aGlzLnBkZmgpKTsKICAgIH0sCgogICAg5LqM57qnOiBhc3luYyBmdW5jdGlvbihpZHMpIHsKICAgICAgICBjb25zdCB7IHBkZmEsIHBkZmgsIHBkIH0gPSB0aGlzOwogICAgICAgIGxldCB1cmwgPSAoQXJyYXkuaXNBcnJheShpZHMpID8gaWRzWzBdIDogaWRzKS5yZXBsYWNlKC9bYCBdL2csICcnKTsKICAgICAgICB1cmwgPSB0aGlzLl9hYnModXJsKTsKICAgICAgICAKICAgICAgICBsZXQgaHRtbCA9IChhd2FpdCByZXEodXJsKSkuY29udGVudDsKICAgICAgICBsZXQgY292ZXIgPSB0aGlzLl9hYnMocGQoaHRtbCwgJy5zaW5nZXJfaW5mbyAucGljIGltZyYmc3JjJykpOwogICAgICAgIGxldCBjb250ZW50ID0gcGRmaChodG1sLCAnLnNpbmdlcl9pbmZvIC5saXN0X3IgLmluZm8gcCYmVGV4dCcpOwogICAgICAgIAogICAgICAgIGxldCB2b2QgPSB7CiAgICAgICAgICAgIHZvZF9uYW1lOiB0aGlzLl9jbGVhbihwZGZoKGh0bWwsICdoMSYmVGV4dCcpIHx8IHBkZmgoaHRtbCwgJ3RpdGxlJiZUZXh0JykpLAogICAgICAgICAgICB2b2RfcGljOiBjb3ZlciwKICAgICAgICAgICAgdm9kX3BsYXlfZnJvbTogJ+eIseeOqemfs+S5kCcsCiAgICAgICAgICAgIHZvZF9jb250ZW50OiBjb250ZW50IHx8ICcnLAogICAgICAgICAgICB2b2RfcmVtYXJrczogJycKICAgICAgICB9OwogICAgICAgIAogICAgICAgIGxldCBwbGF5X2xpc3QgPSBbXTsKICAgICAgICBsZXQgbWFrZUlkID0gKHUsIGxyYyA9ICcnKSA9PiBgJHt1fXx8fCR7Y292ZXJ9fHx8JHtscmN9YDsKICAgICAgICBsZXQgZ2V0THJjTGluayA9IChsaW5rKSA9PiB7CiAgICAgICAgICAgIGxldCBtYXRjaCA9IGxpbmsubWF0Y2goL1wvKHNvbmd8bXAzfHJhZGlvfHJhZGlvbGlzdHxyYWRpb3BsYXkpXC8oW14vXSspXC5odG1sLyk7CiAgICAgICAgICAgIHJldHVybiBtYXRjaCA/IHRoaXMuX2FicyhgL3BsdWcvZG93bi5waHA/YWM9bXVzaWMmbGs9bHJjJmlkPSR7bWF0Y2hbMl19YCkgOiAnJzsKICAgICAgICB9OwoKICAgICAgICBpZiAoL1wvKHZpZGVvfG1wNClcLyhbXi9dKylcLmh0bWwvLnRlc3QodXJsKSkgewogICAgICAgICAgICBsZXQgdmlkID0gdXJsLm1hdGNoKC9cLyh2aWRlb3xtcDQpXC8oW14vXSspXC5odG1sLylbMl07CiAgICAgICAgICAgIGxldCBxdWFsaXRpZXMgPSBbeyBuYW1lOiAn6JOd5YWJJywgcTogJzEwODAnIH0sIHsgbmFtZTogJ+i2hea4hScsIHE6ICc3MjAnIH0sIHsgbmFtZTogJ+mrmOa4hScsIHE6ICc0ODAnIH1dOwogICAgICAgICAgICBxdWFsaXRpZXMuZm9yRWFjaChxID0+IHsKICAgICAgICAgICAgICAgIHBsYXlfbGlzdC5wdXNoKGAke3EubmFtZX0kJHttYWtlSWQodGhpcy5fYWJzKGAvcGx1Zy9kb3duLnBocD9hYz12cGxheSZpZD0ke3ZpZH0mcT0ke3EucX1gKSl9YCk7CiAgICAgICAgICAgIH0pOwogICAgICAgIH0gCiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGxldCBpdGVtcyA9IHBkZmEoaHRtbCwgJy5wbGF5X2xpc3QmJmxpJykgfHwgW107CiAgICAgICAgICAgIGlmICghaXRlbXMubGVuZ3RoKSBpdGVtcyA9IHBkZmEoaHRtbCwgJy5zb25nX2xpc3QmJmxpJykgfHwgW107CiAgICAgICAgICAgIGlmICghaXRlbXMubGVuZ3RoKSBpdGVtcyA9IHBkZmEoaHRtbCwgJy5tdXNpY19saXN0JiZsaScpIHx8IFtdOwogICAgICAgICAgICBpZiAoIWl0ZW1zLmxlbmd0aCkgaXRlbXMgPSBwZGZhKGh0bWwsICd1bCYmbGknKSB8fCBbXTsKICAgICAgICAgICAgaWYgKGl0ZW1zLmxlbmd0aCA9PT0gMCAmJiAvXC8oc29uZ3xtcDN8cmFkaW98cmFkaW9saXN0fHJhZGlvcGxheSlcLy8udGVzdCh1cmwpKSB7CiAgICAgICAgICAgICAgICBwbGF5X2xpc3QucHVzaChg5pKt5pS+JCR7bWFrZUlkKHVybCwgZ2V0THJjTGluayh1cmwpKX1gKTsKICAgICAgICAgICAgfSAKICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBpdGVtcy5mb3JFYWNoKGl0ID0+IHsKICAgICAgICAgICAgICAgICAgICBsZXQgYSA9IHBkKGl0LCAnYSYmaHJlZicpOwogICAgICAgICAgICAgICAgICAgIGlmICghYSkgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIGlmICgvXC8oc29uZ3xtcDN8cmFkaW98cmFkaW9saXN0fHJhZGlvcGxheXx2aWRlb3xtcDQpXC8vLnRlc3QoYSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRpdGxlID0gdGhpcy5fY2xlYW4ocGRmaChpdCwgJy5uYW1lJiZUZXh0JykgfHwgcGQoaXQsICdhJiZUZXh0JykpOwogICAgICAgICAgICAgICAgICAgICAgICBwbGF5X2xpc3QucHVzaChgJHt0aXRsZX0kJHttYWtlSWQodGhpcy5fYWJzKGEpLCBnZXRMcmNMaW5rKGEpKX1gKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB2b2Qudm9kX3BsYXlfdXJsID0gcGxheV9saXN0LmpvaW4oJyMnKTsKICAgICAgICByZXR1cm4gdm9kOwogICAgfSwKCiAgICBsYXp5OiBhc3luYyBmdW5jdGlvbihmbGFnLCBpZCwgZmxhZ3MpIHsKICAgICAgICBsZXQgW3VybCwgcGljLCBscmNVcmxdID0gaWQuc3BsaXQoJ3x8fCcpOwogICAgICAgIHVybCA9ICh1cmwgfHwgJycpLnJlcGxhY2UoL0AuKyQvLCAnJykudHJpbSgpOwogICAgICAgIGxldCBhcGlIZWFkZXJzID0gewogICAgICAgICAgICAnUmVmZXJlcic6IHRoaXMuaG9zdCArICcvJywKICAgICAgICAgICAgJ1VzZXItQWdlbnQnOiB0aGlzLmhlYWRlcnNbJ1VzZXItQWdlbnQnXQogICAgICAgIH07CgogICAgICAgIGxldCBwbGF5VXJsID0gJyc7CiAgICAgICAgbGV0IGlzVmlkZW8gPSB1cmwuaW5jbHVkZXMoJ2Rvd24ucGhwJykgJiYgdXJsLmluY2x1ZGVzKCdhYz12cGxheScpOwogICAgICAgIGlmIChpc1ZpZGVvKSB7CiAgICAgICAgICAgIGxldCByZXMgPSBhd2FpdCByZXEodXJsLCB7IG1ldGhvZDogJ0dFVCcsIHJlZGlyZWN0OiAwLCBoZWFkZXJzOiBhcGlIZWFkZXJzIH0pOwogICAgICAgICAgICBwbGF5VXJsID0gcmVzLmhlYWRlcnMuTG9jYXRpb24gfHwgcmVzLmhlYWRlcnMubG9jYXRpb24gfHwgdGhpcy5fcHJvY2Vzc19hcGlfcmVzcG9uc2UocmVzKTsKICAgICAgICB9CgogICAgICAgIGVsc2UgaWYgKC9cLyhzb25nfG1wM3xyYWRpb3xyYWRpb2xpc3R8cmFkaW9wbGF5KVwvKFteL10rKVwuaHRtbC8udGVzdCh1cmwpKSB7CiAgICAgICAgICAgIGxldCBtaWQgPSB1cmwubWF0Y2goL1wvKFteL10rKVwuaHRtbC8pWzFdOwogICAgICAgICAgICBsZXQgcmVzID0gYXdhaXQgcmVxKHRoaXMuX2FicygnL2pzL3BsYXkucGhwJyksIHsKICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLAogICAgICAgICAgICAgICAgaGVhZGVyczogewogICAgICAgICAgICAgICAgICAgIC4uLmFwaUhlYWRlcnMsCiAgICAgICAgICAgICAgICAgICAgJ1gtUmVxdWVzdGVkLVdpdGgnOiAnWE1MSHR0cFJlcXVlc3QnLAogICAgICAgICAgICAgICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJwogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIGRhdGE6IHsgaWQ6IG1pZCwgdHlwZTogJ211c2ljJyB9CiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBwbGF5VXJsID0gdGhpcy5fcHJvY2Vzc19hcGlfcmVzcG9uc2UocmVzKTsKICAgICAgICB9CgogICAgICAgIGxldCBmaW5hbFVybCA9IHRoaXMuX2FicyhwbGF5VXJsIHx8IHVybCk7CiAgICAgICAgbGV0IHBsYXllckhlYWRlcnMgPSB7CiAgICAgICAgICAgICdVc2VyLUFnZW50JzogYXBpSGVhZGVyc1snVXNlci1BZ2VudCddLAogICAgICAgICAgICAuLi4oZmluYWxVcmwuaW5jbHVkZXMoJzIyYTUuY29tJykgJiYgeyAnUmVmZXJlcic6IGFwaUhlYWRlcnNbJ1JlZmVyZXInXSB9KQogICAgICAgIH07CgogICAgICAgIGlmIChpc1ZpZGVvKSB7CiAgICAgICAgICAgIHJldHVybiB7IHBhcnNlOiAwLCB1cmw6IGZpbmFsVXJsLCBoZWFkZXI6IHBsYXllckhlYWRlcnMgfTsKICAgICAgICB9CgogICAgICAgIGxldCBjb3ZlciA9ICcnOwogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGxldCBwYWdlUmVzID0gYXdhaXQgcmVxKHVybCwgeyBoZWFkZXJzOiBhcGlIZWFkZXJzIH0pOwogICAgICAgICAgICBsZXQgcGFnZUh0bWwgPSB0eXBlb2YgcGFnZVJlcyA9PT0gJ29iamVjdCcgPyBwYWdlUmVzLmNvbnRlbnQgOiBwYWdlUmVzOwogICAgICAgICAgICBsZXQgb2dJbWFnZU1hdGNoID0gcGFnZUh0bWwubWF0Y2goLzxtZXRhW14+XStwcm9wZXJ0eT0ib2c6aW1hZ2UiW14+XStjb250ZW50PSIoW14iXSspIltePl0qPi9pKTsKICAgICAgICAgICAgaWYgKG9nSW1hZ2VNYXRjaCAmJiBvZ0ltYWdlTWF0Y2hbMV0pIHsKICAgICAgICAgICAgICAgIGNvdmVyID0gb2dJbWFnZU1hdGNoWzFdOwogICAgICAgICAgICB9CiAgICAgICAgfSBjYXRjaCB7fQoKICAgICAgICBsZXQgbHJjRGF0YSA9ICcnOwogICAgICAgIGlmIChscmNVcmwpIHsKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIGxldCBscmNSZXMgPSBhd2FpdCByZXEobHJjVXJsLCB7IGhlYWRlcnM6IGFwaUhlYWRlcnMgfSk7CiAgICAgICAgICAgICAgICBsZXQgY29udGVudCA9IHR5cGVvZiBscmNSZXMgPT09ICdvYmplY3QnID8gbHJjUmVzLmNvbnRlbnQgOiBscmNSZXM7CiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnRlbnQgPT09ICdzdHJpbmcnICYmIGNvbnRlbnQuaW5jbHVkZXMoJ1snKSAmJiBjb250ZW50LmluY2x1ZGVzKCddJykpIHsKICAgICAgICAgICAgICAgICAgICBscmNEYXRhID0gY29udGVudDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBjYXRjaCB7fQogICAgICAgIH0KCiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgcGFyc2U6IDAsCiAgICAgICAgICAgIHVybDogZmluYWxVcmwsCiAgICAgICAgICAgIGhlYWRlcjogcGxheWVySGVhZGVycywKICAgICAgICAgICAgbHJjOiBscmNEYXRhLAogICAgICAgICAgICBwaWM6IGNvdmVyLAogICAgICAgICAgICBjb3ZlcjogY292ZXIsCiAgICAgICAgICAgIGhlaWdodDogNzIwCiAgICAgICAgfTsKICAgIH0sCgogICAgX3Byb2Nlc3NfYXBpX3Jlc3BvbnNlOiAocmVzKSA9PiB7CiAgICAgICAgaWYgKCFyZXMpIHJldHVybiAnJzsKICAgICAgICBjb25zdCBjb250ZW50ID0gdHlwZW9mIHJlcyA9PT0gJ29iamVjdCcgPyByZXMuY29udGVudCA6IHJlczsKICAgICAgICBjb25zdCB0cmltbWVkID0gY29udGVudC50cmltKCk7CiAgICAgICAgbGV0IGpzb247CiAgICAgICAgdHJ5IHsganNvbiA9IEpTT04ucGFyc2UoY29udGVudCk7IH0gY2F0Y2gge30gCiAgICAgICAgcmV0dXJuIGpzb24/LnVybCA/IGpzb24udXJsLnJlcGxhY2UoL1xcXC8vZywgJy8nKSA6ICh0cmltbWVkLnN0YXJ0c1dpdGgoJ2h0dHAnKSA/IHRyaW1tZWQgOiAnJyk7CiAgICB9Cn07 \ No newline at end of file diff --git "a/spider/js/\347\261\263\345\205\224\351\237\263\344\271\220[\345\220\254].js" "b/spider/js/\347\261\263\345\205\224\351\237\263\344\271\220[\345\220\254].js" index 6a2a6720..92050aca 100644 --- "a/spider/js/\347\261\263\345\205\224\351\237\263\344\271\220[\345\220\254].js" +++ "b/spider/js/\347\261\263\345\205\224\351\237\263\344\271\220[\345\220\254].js" @@ -9,51 +9,4 @@ }) */ -var rule = { - title: '米兔音乐', - host: 'https://api.qqmp3.vip', - url: '/api/fyclass', - searchUrl: '/api/songs.php?type=search&keyword=**', - class_name: '热门歌曲&新歌曲&随机歌曲', - class_url: 'songs.php&songs.php?type=new&songs.php?type=rand', - searchable: 2, - quickSearch: 0, - filterable: 0, - play_parse: true, - limit: 6, - double: true, - headers: { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; V2284A Build/V417IR; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.61 Safari/537.36', - 'Accept': '*/*', - 'Origin': 'https://www.qqmp3.vip', - 'referer': 'https://www.qqmp3.vip', - 'x-requested-with': 'com.mmbox.xbrowser', - 'Sec-Fetch-Site': 'same-site', - 'Sec-Fetch-Mode': 'cors', - 'Sec-Fetch-Dest': 'empty', - 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7' - }, - 推荐: '*', - 一级: 'json:data;name;pic;artist;rid', - 二级: '*', - 搜索: 'json:data;name;pic;artist;rid', - lazy: async function() { - let ridMatch = this.input.match(/api\/([^/?]+)/); - if (!ridMatch) return this.input; - let rid = ridMatch[1]; - let api = 'https://api.qqmp3.vip/api/kw.php?rid=' + rid; - // console.log('解析接口:', api); - let json = await request(api); - let data = JSON.parse(json); - if (data.code === 200 && data.data?.url) { - return { - parse: 0, - url: data.data.url, - header: this.headers, - lrc: data.data.lrc || '', - playMode: 'repeat' - }; - } - return this.input; - }, -}; \ No newline at end of file +dmFyIHJ1bGUgPSB7CiAgdGl0bGU6ICfnsbPlhZTpn7PkuZAnLAogIGhvc3Q6ICdodHRwczovL2FwaS5xcW1wMy52aXAnLAogIHVybDogJy9hcGkvZnljbGFzcycsCiAgc2VhcmNoVXJsOiAnL2FwaS9zb25ncy5waHA/dHlwZT1zZWFyY2gma2V5d29yZD0qKicsCiAgY2xhc3NfbmFtZTogJ+eDremXqOatjOabsibmlrDmrYzmm7Im6ZqP5py65q2M5puyJywKICBjbGFzc191cmw6ICdzb25ncy5waHAmc29uZ3MucGhwP3R5cGU9bmV3JnNvbmdzLnBocD90eXBlPXJhbmQnLAogIHNlYXJjaGFibGU6IDIsCiAgcXVpY2tTZWFyY2g6IDAsCiAgZmlsdGVyYWJsZTogMCwKICBwbGF5X3BhcnNlOiB0cnVlLAogIGxpbWl0OiA2LAogIGRvdWJsZTogdHJ1ZSwKICBoZWFkZXJzOiB7CiAgICAnVXNlci1BZ2VudCc6ICdNb3ppbGxhLzUuMCAoTGludXg7IEFuZHJvaWQgMTI7IFYyMjg0QSBCdWlsZC9WNDE3SVI7IHd2KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBWZXJzaW9uLzQuMCBDaHJvbWUvMTAxLjAuNDk1MS42MSBTYWZhcmkvNTM3LjM2JywKICAgICdBY2NlcHQnOiAnKi8qJywKICAgICdPcmlnaW4nOiAnaHR0cHM6Ly93d3cucXFtcDMudmlwJywKICAgICdyZWZlcmVyJzogJ2h0dHBzOi8vd3d3LnFxbXAzLnZpcCcsCiAgICAneC1yZXF1ZXN0ZWQtd2l0aCc6ICdjb20ubW1ib3gueGJyb3dzZXInLAogICAgJ1NlYy1GZXRjaC1TaXRlJzogJ3NhbWUtc2l0ZScsCiAgICAnU2VjLUZldGNoLU1vZGUnOiAnY29ycycsCiAgICAnU2VjLUZldGNoLURlc3QnOiAnZW1wdHknLAogICAgJ0FjY2VwdC1MYW5ndWFnZSc6ICd6aC1DTix6aDtxPTAuOSxlbi1VUztxPTAuOCxlbjtxPTAuNycKICB9LAogIOaOqOiNkDogJyonLAogIOS4gOe6pzogJ2pzb246ZGF0YTtuYW1lO3BpYzthcnRpc3Q7cmlkJywKICDkuoznuqc6ICcqJywKICDmkJzntKI6ICdqc29uOmRhdGE7bmFtZTtwaWM7YXJ0aXN0O3JpZCcsCiAgbGF6eTogYXN5bmMgZnVuY3Rpb24oKSB7CiAgICBsZXQgcmlkTWF0Y2ggPSB0aGlzLmlucHV0Lm1hdGNoKC9hcGlcLyhbXi8/XSspLyk7CiAgICBpZiAoIXJpZE1hdGNoKSByZXR1cm4gdGhpcy5pbnB1dDsKICAgIGxldCByaWQgPSByaWRNYXRjaFsxXTsKICAgIGxldCBhcGkgPSAnaHR0cHM6Ly9hcGkucXFtcDMudmlwL2FwaS9rdy5waHA/cmlkPScgKyByaWQ7CiAgLy8gIGNvbnNvbGUubG9nKCfop6PmnpDmjqXlj6M6JywgYXBpKTsKICAgIGxldCBqc29uID0gYXdhaXQgcmVxdWVzdChhcGkpOwogICAgbGV0IGRhdGEgPSBKU09OLnBhcnNlKGpzb24pOwogICAgaWYgKGRhdGEuY29kZSA9PT0gMjAwICYmIGRhdGEuZGF0YT8udXJsKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgcGFyc2U6IDAsCiAgICAgICAgICAgIHVybDogZGF0YS5kYXRhLnVybCwKICAgICAgICAgICAgaGVhZGVyOiB0aGlzLmhlYWRlcnMsCiAgICAgICAgICAgIGxyYzogZGF0YS5kYXRhLmxyYyB8fCAnJywKICAgICAgICAgICAgcGxheU1vZGU6ICdyZXBlYXQnCiAgICAgICAgfTsKICAgIH0KICAgIHJldHVybiB0aGlzLmlucHV0OwogIH0sCn07 \ No newline at end of file From 5a955fce36b3eb4a7b2b4311ec398e41232f8490 Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Wed, 21 Jan 2026 16:20:58 +0800 Subject: [PATCH 059/101] =?UTF-8?q?Change=20all=20const=20to=20let=20in=20?= =?UTF-8?q?=E9=BA=BB=E9=9B=80=E8=A7=86=E9=A2=91.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\272\273\351\233\200\350\247\206\351\242\221.js" | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 "spider/js/\351\272\273\351\233\200\350\247\206\351\242\221.js" diff --git "a/spider/js/\351\272\273\351\233\200\350\247\206\351\242\221.js" "b/spider/js/\351\272\273\351\233\200\350\247\206\351\242\221.js" new file mode 100644 index 00000000..b63b250d --- /dev/null +++ "b/spider/js/\351\272\273\351\233\200\350\247\206\351\242\221.js" @@ -0,0 +1,13 @@ +/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 0, + title: '麻雀视频', + author: 'EylinSir', + '类型': '影视', + lang: 'ds' +}) +*/ + +dmFyIHJ1bGUgPSB7CiAgICDnsbvlnos6ICflvbHop4YnLAogICAgYXV0aG9yOiAnRXlsaW5TaXInLAogICAgdGl0bGU6ICfpurvpm4Dop4bpopEnLAogICAgaG9zdDogJ2h0dHBzOi8vd3d3Lm1xdHYuY2MnLAogICAgaG9tZVVybDogJ2h0dHBzOi8vd3d3Lm1xdHYuY2MnLAogICAgdXJsOiAnL2xpYnMvVm9kTGlzdC5hcGkucGhwP3R5cGU9ZnljbGFzcyZyYW5rPXJhbmtob3QmY2F0PSZ5ZWFyPSZhcmVhPSZwYWdlPWZ5cGFnZSZ0b2tlbj1meXRva2VuJywKICAgIHNlYXJjaFVybDogJy9saWJzL1ZvZExpc3QuYXBpLnBocD9zZWFyY2g9KiomdG9rZW49Znl0b2tlbicsCiAgICBzZWFyY2hhYmxlOiAxLAogICAgcXVpY2tTZWFyY2g6IDAsCiAgICBmaWx0ZXJhYmxlOiAxLAogICAgdGltZW91dDogMTAwMDAsCiAgICBwbGF5X3BhcnNlOiB0cnVlLAogICAga2V5OiAnTWN4b3NAbXVjaG8hbm1tZScsCiAgICBoZWFkZXJzOiB7CiAgICAgICAgJ1VzZXItQWdlbnQnOiAnTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzE0Mi4wLjAuMCBTYWZhcmkvNTM3LjM2JywKICAgICAgICAnYWNjZXB0LWxhbmd1YWdlJzogJ3poLUNOLHpoO3E9MC45JywKICAgICAgICAnc2VjLWNoLXVhJzogJyJHb29nbGUgQ2hyb21lIjt2PSIxNDMiLCAiQ2hyb21pdW0iO3Y9IjE0MyIsICJOb3QgQShCcmFuZCI7dj0iMjQiJywKICAgICAgICAnY2FjaGUtY29udHJvbCc6ICduby1jYWNoZScsCiAgICAgICAgJ3ByYWdtYSc6ICduby1jYWNoZScsCiAgICAgICAgJ3NlYy1jaC11YS1tb2JpbGUnOiAnPzAnLAogICAgICAgICdzZWMtY2gtdWEtcGxhdGZvcm0nOiAnIldpbmRvd3MiJywKICAgICAgICAnc2VjLWZldGNoLXNpdGUnOiAnc2FtZS1vcmlnaW4nCiAgICB9LAogICAgCiAgICBnZXRUb2tlbjogYXN5bmMgZnVuY3Rpb24gKHBhdGgsIHJlZlBhdGggPSAnJykgewogICAgICAgIGxldCBoZWFkZXJzID0gewogICAgICAgICAgICAuLi50aGlzLmhlYWRlcnMsCiAgICAgICAgICAgICdBY2NlcHQnOiAndGV4dC9odG1sLGFwcGxpY2F0aW9uL3hodG1sK3htbCxhcHBsaWNhdGlvbi94bWw7cT0wLjksaW1hZ2UvYXZpZixpbWFnZS93ZWJwLGltYWdlL2FwbmcsKi8qO3E9MC44LGFwcGxpY2F0aW9uL3NpZ25lZC1leGNoYW5nZTt2PWIzO3E9MC43JywKICAgICAgICAgICAgJ3ByaW9yaXR5JzogJ3U9MCwgaScsCiAgICAgICAgICAgICdzZWMtZmV0Y2gtZGVzdCc6ICdkb2N1bWVudCcsCiAgICAgICAgICAgICdzZWMtZmV0Y2gtbW9kZSc6ICduYXZpZ2F0ZScsCiAgICAgICAgICAgICdzZWMtZmV0Y2gtdXNlcic6ICc/MScsCiAgICAgICAgICAgICd1cGdyYWRlLWluc2VjdXJlLXJlcXVlc3RzJzogJzEnCiAgICAgICAgfTsKICAgICAgICBpZiAocmVmUGF0aCkgaGVhZGVyc1sncmVmZXJlciddID0gYCR7dGhpcy5ob3N0fSR7cmVmUGF0aH1gOwogICAgICAgIGxldCByZXNwID0gYXdhaXQgX2ZldGNoKGAke3RoaXMuaG9zdH0ke3BhdGh9YCwgeyBoZWFkZXJzIH0pOwogICAgICAgIGxldCBodG1sID0gYXdhaXQgcmVzcC50ZXh0KCk7CiAgICAgICAgbGV0IG1hdGNoID0gaHRtbC5tYXRjaCgvd2luZG93XC5wYWdlaWRccz89XHM/JyguKj8pJzsvaSk7CiAgICAgICAgbGV0IHBhZ2VJZCA9IG1hdGNoID8gbWF0Y2hbMV0gOiAnJzsKICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGVEYXRhKHBhZ2VJZCk7CiAgICB9LAoKICAgIGVuY29kZURhdGE6IGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgICAgbGV0IGpzb25TdHIgPSBKU09OLnN0cmluZ2lmeShkYXRhKTsKICAgICAgICBsZXQgYjY0XzEgPSBidG9hKHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChqc29uU3RyKSkpOwogICAgICAgIGxldCB4b3JfcmVzdWx0ID0gJyc7CiAgICAgICAgbGV0IGtleUxlbiA9IHRoaXMua2V5Lmxlbmd0aDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGI2NF8xLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGxldCBjaGFyQ29kZSA9IGI2NF8xLmNoYXJDb2RlQXQoaSkgXiB0aGlzLmtleS5jaGFyQ29kZUF0KGkgJSBrZXlMZW4pOwogICAgICAgICAgICB4b3JfcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhckNvZGUpOwogICAgICAgIH0KICAgICAgICBsZXQgYjY0XzIgPSBidG9hKHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudCh4b3JfcmVzdWx0KSkpOwogICAgICAgIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQoYjY0XzIpOwogICAgfSwKCiAgICBkZWNvZGVEYXRhOiBmdW5jdGlvbiAoZW5jb2RlZFN0cikgewogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGxldCBiYXNlNjREZWNvZGUgPSAoc3RyKSA9PiB7CiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQoZXNjYXBlKGF0b2Ioc3RyKSkpOwogICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiAnJzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfTsKICAgICAgICAgICAgCiAgICAgICAgICAgIGxldCBkZWNvZGVkU3RlcDFTdHIgPSBiYXNlNjREZWNvZGUoZW5jb2RlZFN0cik7CiAgICAgICAgICAgIGxldCB4b3JSZXN1bHQgPSAnJzsKICAgICAgICAgICAgbGV0IGtleUxlbiA9IHRoaXMua2V5Lmxlbmd0aDsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkZWNvZGVkU3RlcDFTdHIubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgIHhvclJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGRlY29kZWRTdGVwMVN0ci5jaGFyQ29kZUF0KGkpIF4gdGhpcy5rZXkuY2hhckNvZGVBdChpICUga2V5TGVuKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICAgIGxldCBkZWNvZGVkU3RlcDJTdHIgPSBiYXNlNjREZWNvZGUoeG9yUmVzdWx0KTsKICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoZGVjb2RlZFN0ZXAyU3RyKTsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0RlY29kZSBlcnJvcjonLCBlKTsKICAgICAgICAgICAgcmV0dXJuIHt9OwogICAgICAgIH0KICAgIH0sCiAgICAKICAgIGdldEhlYWRlcnMyOiBmdW5jdGlvbiAocmVmUGF0aCA9ICcnKSB7CiAgICAgICAgbGV0IGhlYWRlcnMgPSB7CiAgICAgICAgICAgIC4uLnRoaXMuaGVhZGVycywKICAgICAgICAgICAgJ0FjY2VwdCc6ICdhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFzY3JpcHQsICovKjsgcT0wLjAxJywKICAgICAgICAgICAgJ3ByaW9yaXR5JzogJ3U9MSwgaScsCiAgICAgICAgICAgICdzZWMtZmV0Y2gtZGVzdCc6ICdlbXB0eScsCiAgICAgICAgICAgICdzZWMtZmV0Y2gtbW9kZSc6ICdjb3JzJywKICAgICAgICAgICAgJ3gtcmVxdWVzdGVkLXdpdGgnOiAnWE1MSHR0cFJlcXVlc3QnCiAgICAgICAgfTsKICAgICAgICBpZiAocmVmUGF0aCkgaGVhZGVyc1sncmVmZXJlciddID0gYCR7dGhpcy5ob3N0fSR7cmVmUGF0aH1gOwogICAgICAgIHJldHVybiBoZWFkZXJzOwogICAgfSwKCiAgICBhcnIydm9kczogZnVuY3Rpb24gKGFycikgewogICAgICAgIHJldHVybiAoYXJyIHx8IFtdKS5tYXAoaSA9PiAoewogICAgICAgICAgICB0aXRsZTogaS50aXRsZSwKICAgICAgICAgICAgdXJsOiBgJHt0aGlzLmhvc3R9JHtpLnVybH1gLAogICAgICAgICAgICBkZXNjOiBpLnJlbWFyaywKICAgICAgICAgICAgcGljX3VybDogaS5pbWcsCiAgICAgICAgICAgIHZvZF95ZWFyOiBpLnllYXIgfHwgJycKICAgICAgICB9KSk7CiAgICB9LAogICAgCiAgICDpooTlpITnkIY6IGFzeW5jIGZ1bmN0aW9uICgpIHt9LAoKICAgIGNsYXNzX3BhcnNlOiBhc3luYyBmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgY2xhc3M6IFsKICAgICAgICAgICAgICAgIHsgJ3R5cGVfaWQnOiAnL3R5cGUvbW92aWUnLCAndHlwZV9uYW1lJzogJ+eUteW9sScgfSwKICAgICAgICAgICAgICAgIHsgJ3R5cGVfaWQnOiAnL3R5cGUvdHYnLCAndHlwZV9uYW1lJzogJ+eUteinhuWJpycgfSwKICAgICAgICAgICAgICAgIHsgJ3R5cGVfaWQnOiAnL3R5cGUvdmEnLCAndHlwZV9uYW1lJzogJ+e7vOiJuicgfSwKICAgICAgICAgICAgICAgIHsgJ3R5cGVfaWQnOiAnL3R5cGUvY3QnLCAndHlwZV9uYW1lJzogJ+WKqOa8qycgfQogICAgICAgICAgICBdLAogICAgICAgICAgICBmaWx0ZXJzOiB7fQogICAgICAgIH07CiAgICB9LAogICAgCiAgICDmjqjojZA6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgdG9rZW4gPSBhd2FpdCB0aGlzLmdldFRva2VuKCcvJyk7CiAgICAgICAgbGV0IHVybCA9IGAke3RoaXMuaG9zdH0vbGlicy9Wb2RMaXN0LmFwaS5waHA/aG9tZT1pbmRleCZ0b2tlbj0ke3Rva2VufWA7CiAgICAgICAgbGV0IHJlc3AgPSBhd2FpdCBfZmV0Y2godXJsLCB7IGhlYWRlcnM6IHRoaXMuZ2V0SGVhZGVyczIoJy8nKSB9KTsKICAgICAgICBsZXQganNvbiA9IEpTT04ucGFyc2UoYXdhaXQgcmVzcC50ZXh0KCkpOwogICAgICAgIGxldCB2aWRlb3MgPSBbXTsKICAgICAgICBpZiAoanNvbi5kYXRhICYmIGpzb24uZGF0YS5tb3ZpZSkgewogICAgICAgICAgICBmb3IgKGxldCBpIG9mIGpzb24uZGF0YS5tb3ZpZSkgewogICAgICAgICAgICAgICAgdmlkZW9zLnB1c2goLi4udGhpcy5hcnIydm9kcyhpLnNob3cpKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gc2V0UmVzdWx0KHZpZGVvcyk7CiAgICB9LAogICAgCiAgICDkuIDnuqc6IGFzeW5jIGZ1bmN0aW9uICh0aWQsIHBnLCBmaWx0ZXIsIGV4dGVuZCkgewogICAgICAgIGxldCB0eXBlS2V5ID0gdGlkLnNwbGl0KCcvJylbMl07CiAgICAgICAgbGV0IHRva2VuID0gYXdhaXQgdGhpcy5nZXRUb2tlbih0aWQsICcvJyk7CiAgICAgICAgbGV0IHVybCA9IGAke3RoaXMuaG9zdH0vbGlicy9Wb2RMaXN0LmFwaS5waHA/dHlwZT0ke3R5cGVLZXl9JnJhbms9cmFua2hvdCZjYXQ9JnllYXI9JmFyZWE9JnBhZ2U9JHtwZ30mdG9rZW49JHt0b2tlbn1gOwogICAgICAgIGxldCByZXNwID0gYXdhaXQgX2ZldGNoKHVybCwgeyBoZWFkZXJzOiB0aGlzLmdldEhlYWRlcnMyKHRpZCkgfSk7CiAgICAgICAgbGV0IGpzb24gPSBKU09OLnBhcnNlKGF3YWl0IHJlc3AudGV4dCgpKTsKICAgICAgICBsZXQgdmlkZW9zID0gdGhpcy5hcnIydm9kcyhqc29uLmRhdGEpOwogICAgICAgIHJldHVybiBzZXRSZXN1bHQodmlkZW9zKTsKICAgIH0sCiAgICAKICAgIOS6jOe6pzogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGxldCBpZCA9IHRoaXMuaW5wdXQucmVwbGFjZShgJHt0aGlzLmhvc3R9YCwgJycpOwogICAgICAgIGxldCByZWFsSWQgPSBpZC5zcGxpdCgnLycpW2lkLnNwbGl0KCcvJykubGVuZ3RoIC0gMV07CiAgICAgICAgbGV0IHRva2VuID0gYXdhaXQgdGhpcy5nZXRUb2tlbihpZCwgJy8nKTsKICAgICAgICBsZXQgdXJsID0gYCR7dGhpcy5ob3N0fS9saWJzL1ZvZEluZm8uYXBpLnBocD90eXBlPWN0JmlkPSR7cmVhbElkfSZ0b2tlbj0ke3Rva2VufWA7CiAgICAgICAgbGV0IHJlc3AgPSBhd2FpdCBfZmV0Y2godXJsLCB7IGhlYWRlcnM6IHRoaXMuZ2V0SGVhZGVyczIoaWQpIH0pOwogICAgICAgIGxldCBqc29uID0gSlNPTi5wYXJzZShhd2FpdCByZXNwLnRleHQoKSk7CiAgICAgICAgbGV0IGRhdGEgPSBqc29uLmRhdGE7CiAgICAgICAgbGV0IHBsYXlBcGkgPSBkYXRhLnBsYXlhcGkgfHwgW107CiAgICAgICAgbGV0IHBhcnNlcyA9IHBsYXlBcGkKICAgICAgICAgICAgLmZpbHRlcihpID0+IHR5cGVvZiBpID09PSAnb2JqZWN0JyAmJiBpICE9PSBudWxsICYmIGkudXJsICYmIHR5cGVvZiBpLnVybCA9PT0gJ3N0cmluZycpCiAgICAgICAgICAgIC5tYXAoaSA9PiBpLnVybC5zdGFydHNXaXRoKCcvLycpID8gYGh0dHBzOiR7aS51cmx9YCA6IGkudXJsKQogICAgICAgICAgICAuam9pbignLCcpOwogICAgICAgIGxldCBzaG93cyA9IFtdOwogICAgICAgIGxldCBwbGF5VXJscyA9IFtdOwogICAgICAgIGlmIChkYXRhLnBsYXlpbmZvKSB7CiAgICAgICAgICAgIGZvciAobGV0IGogb2YgZGF0YS5wbGF5aW5mbykgewogICAgICAgICAgICAgICAgbGV0IHVybHMgPSBbXTsKICAgICAgICAgICAgICAgIGZvciAobGV0IGsgb2Ygai5wbGF5ZXIpIHsKICAgICAgICAgICAgICAgICAgICB1cmxzLnB1c2goYCR7ay5ub30kJHtrLnVybH1AJHtwYXJzZXN9YCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAodXJscy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgcGxheVVybHMucHVzaCh1cmxzLmpvaW4oJyMnKSk7CiAgICAgICAgICAgICAgICAgICAgc2hvd3MucHVzaChqLmNuc2l0ZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgCiAgICAgICAgbGV0IFZPRCA9IHsKICAgICAgICAgICAgdm9kX2lkOiBpZCwKICAgICAgICAgICAgdm9kX25hbWU6IGRhdGEudGl0bGUsCiAgICAgICAgICAgIHZvZF9waWM6IGRhdGEuaW1nLAogICAgICAgICAgICB2b2RfcmVtYXJrczogZGF0YS5yZW1hcmssCiAgICAgICAgICAgIHZvZF95ZWFyOiBkYXRhLnllYXIsCiAgICAgICAgICAgIHZvZF9hcmVhOiBkYXRhLmFyZWEsCiAgICAgICAgICAgIHZvZF9hY3RvcjogZGF0YS5hY3RvciwKICAgICAgICAgICAgdm9kX2RpcmVjdG9yOiBkYXRhLmRpcmVjdG9yLAogICAgICAgICAgICB2b2RfY29udGVudDogJycsCiAgICAgICAgICAgIHZvZF9wbGF5X2Zyb206IHNob3dzLmpvaW4oJyQkJCcpLAogICAgICAgICAgICB2b2RfcGxheV91cmw6IHBsYXlVcmxzLmpvaW4oJyQkJCcpLAogICAgICAgICAgICB0eXBlX25hbWU6ICcnCiAgICAgICAgfTsKICAgICAgICByZXR1cm4gVk9EOwogICAgfSwKICAgIAogICAg5pCc57SiOiBhc3luYyBmdW5jdGlvbiAoKSB7CiAgICAgICAgbGV0IHBhdGggPSBgL3NlYXJjaC8ke2VuY29kZVVSSUNvbXBvbmVudCh0aGlzLktFWSl9YDsKICAgICAgICBsZXQgdG9rZW4gPSBhd2FpdCB0aGlzLmdldFRva2VuKHBhdGgsICcvJyk7CiAgICAgICAgbGV0IHVybCA9IGAke3RoaXMuaG9zdH0vbGlicy9Wb2RMaXN0LmFwaS5waHA/c2VhcmNoPSR7ZW5jb2RlVVJJQ29tcG9uZW50KHRoaXMuS0VZKX0mdG9rZW49JHt0b2tlbn1gOwogICAgICAgIGxldCByZXNwID0gYXdhaXQgX2ZldGNoKHVybCwgeyBoZWFkZXJzOiB0aGlzLmdldEhlYWRlcnMyKHBhdGgpIH0pOwogICAgICAgIGxldCBqc29uID0gSlNPTi5wYXJzZShhd2FpdCByZXNwLnRleHQoKSk7CiAgICAgICAgbGV0IGRlY29kZURhdGEgPSB0aGlzLmRlY29kZURhdGEoanNvbi5kYXRhKTsKICAgICAgICBsZXQgdmlkZW9zID0gW107CiAgICAgICAgaWYgKGRlY29kZURhdGEudm9kX2FsbCkgewogICAgICAgICAgICBmb3IgKGxldCBpIG9mIGRlY29kZURhdGEudm9kX2FsbCkgewogICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpID09PSAnb2JqZWN0JyAmJiBpICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgdmlkZW9zLnB1c2goLi4udGhpcy5hcnIydm9kcyhpLnNob3cpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gc2V0UmVzdWx0KHZpZGVvcyk7CiAgICB9LAogICAgCiAgICBsYXp5OiBhc3luYyBmdW5jdGlvbiAoKSB7CiAgICAgICAgbGV0IFtyYXdVcmwsIHBhcnNlc1N0ciA9ICcnXSA9IHRoaXMuaW5wdXQuc3BsaXQoJ0AnKTsKICAgICAgICBsZXQgcGFyc2VzID0gcGFyc2VzU3RyLnNwbGl0KCcsJyk7CiAgICAgICAgbGV0IGp4ID0gMDsKICAgICAgICBsZXQgc25pZmYgPSAwOwogICAgICAgIGxldCB1cmwgPSAnJzsKICAgICAgICBpZiAocmF3VXJsLnN0YXJ0c1dpdGgoJ2h0dHAnKSAmJiAvKD86d3d3XC5pcWl5aXx2XC5xcXx2XC55b3VrdXx3d3dcLm1ndHZ8d3d3XC5iaWxpYmlsaSlcLmNvbS8udGVzdChyYXdVcmwpKSB7CiAgICAgICAgICAgIHVybCA9IHJhd1VybDsKICAgICAgICAgICAganggPSAxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGxldCBmaXJzdFZhbGlkUGFyc2UgPSBwYXJzZXMuZmluZChqID0+IGouc3RhcnRzV2l0aCgnaHR0cCcpKTsKICAgICAgICAgICAgaWYgKGZpcnN0VmFsaWRQYXJzZSkgewogICAgICAgICAgICAgICAgdXJsID0gYCR7Zmlyc3RWYWxpZFBhcnNlfSR7cmF3VXJsfWA7CiAgICAgICAgICAgICAgICBzbmlmZiA9IDE7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB1cmwgPSByYXdVcmw7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgcGFyc2U6IHNuaWZmIHx8IGp4LAogICAgICAgICAgICB1cmwsCiAgICAgICAgICAgIGhlYWRlcjogeyAnVXNlci1BZ2VudCc6IHRoaXMuaGVhZGVyc1snVXNlci1BZ2VudCddIH0KICAgICAgICB9OwogICAgfQp9Ow== \ No newline at end of file From b2cad32883f96ed705778961b6d2e21eeff67fca Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Wed, 21 Jan 2026 16:21:53 +0800 Subject: [PATCH 060/101] Update multiple files --- "spider/js/3Q\345\275\261\350\247\206.js" | 13 + ...\345\233\255\350\241\214[\346\210\217].js" | 249 +----------------- ...55\346\222\255\345\275\261\350\247\206.js" | 13 + ...\345\260\217\350\257\264[\344\271\246].js" | 1 + ...\347\225\205\345\220\254[\345\220\254].js" | 3 +- ...\347\237\255\345\211\247[\347\237\255].js" | 3 +- ...75\346\226\260\345\244\247\345\205\250.js" | 13 + 7 files changed, 45 insertions(+), 250 deletions(-) create mode 100644 "spider/js/3Q\345\275\261\350\247\206.js" create mode 100644 "spider/js/\347\203\255\346\222\255\345\275\261\350\247\206.js" create mode 100644 "spider/js/\350\277\275\346\226\260\345\244\247\345\205\250.js" diff --git "a/spider/js/3Q\345\275\261\350\247\206.js" "b/spider/js/3Q\345\275\261\350\247\206.js" new file mode 100644 index 00000000..7236e339 --- /dev/null +++ "b/spider/js/3Q\345\275\261\350\247\206.js" @@ -0,0 +1,13 @@ +/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 0, + title: '3Q影视', + author: 'EylinSir', + '类型': '影视', + lang: 'ds' +}) +*/ + +dmFyIHJ1bGUgPSB7CiAgICDnsbvlnos6ICflvbHop4YnLAogICAgYXV0aG9yOiAnRXlsaW5TaXInLAogICAgdGl0bGU6ICczUeW9seinhicsCiAgICBkZXNjOiAnM1HlvbHop4bmupAnLAogICAgaG9zdDogJ2h0dHBzOi8vcXFxeXMuY29tJywKICAgIGhvbWVVcmw6ICdodHRwczovL3FxcXlzLmNvbScsCiAgICB1cmw6ICcvYXBpLnBocC9maWx0ZXIvdm9kP3R5cGVfbmFtZT1meWNsYXNzJnBhZ2U9ZnlwYWdlJnNvcnQ9aGl0cycsCiAgICBzZWFyY2hVcmw6ICcvYXBpLnBocC9zZWFyY2gvaW5kZXg/d2Q9KiomcGFnZT1meXBhZ2UmbGltaXQ9MTUnLAogICAgc2VhcmNoYWJsZTogMSwKICAgIHF1aWNrU2VhcmNoOiAwLAogICAgZmlsdGVyYWJsZTogMSwKICAgIHRpbWVvdXQ6IDEwMDAwLAogICAgcGxheV9wYXJzZTogdHJ1ZSwKICAgIGhlYWRlcnM6IHsKICAgICAgICAnVXNlci1BZ2VudCc6ICdNb3ppbGxhLzUuMCAoV2luZG93cyBOVCAxMC4wOyBXaW42NDsgeDY0KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvMTQyLjAuMC4wIFNhZmFyaS81MzcuMzYnLAogICAgICAgICdhY2NlcHQtbGFuZ3VhZ2UnOiAnemgtQ04semg7cT0wLjknLAogICAgICAgICdjYWNoZS1jb250cm9sJzogJ25vLWNhY2hlJywKICAgICAgICAncHJhZ21hJzogJ25vLWNhY2hlJywKICAgICAgICAncHJpb3JpdHknOiAndT0xLCBpJywKICAgICAgICAnc2VjLWNoLXVhJzogJyJDaHJvbWl1bSI7dj0iMTQyIiwgIkdvb2dsZSBDaHJvbWUiO3Y9IjE0MiIsICJOb3RfQSBCcmFuZCI7dj0iOTkiJywKICAgICAgICAnc2VjLWNoLXVhLW1vYmlsZSc6ICI/MCIsCiAgICAgICAgJ3NlYy1jaC11YS1wbGF0Zm9ybSc6ICciV2luZG93cyInLAogICAgICAgICdzZWMtZmV0Y2gtZGVzdCc6ICJlbXB0eSIsCiAgICAgICAgJ3NlYy1mZXRjaC1tb2RlJzogImNvcnMiLAogICAgICAgICdzZWMtZmV0Y2gtc2l0ZSc6ICJzYW1lLW9yaWdpbiIKICAgIH0sCiAgICAKCgogICAganNvbjJ2b2RzOiBmdW5jdGlvbiAoYXJyKSB7CiAgICAgICAgbGV0IHZpZGVvcyA9IFtdOwogICAgICAgIGZvciAoY29uc3QgaSBvZiBhcnIpIHsKICAgICAgICAgICAgbGV0IHR5cGVfbmFtZSA9IGkudHlwZV9uYW1lIHx8ICcnOwogICAgICAgICAgICBpZiAoaS52b2RfY2xhc3MpIHsKICAgICAgICAgICAgICAgIHR5cGVfbmFtZSA9IHR5cGVfbmFtZSArICcsJyArIGkudm9kX2NsYXNzOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZpZGVvcy5wdXNoKHsKICAgICAgICAgICAgICAgIHRpdGxlOiBpLnZvZF9uYW1lLAogICAgICAgICAgICAgICAgdXJsOiBgJHt0aGlzLmhvc3R9L2FwaS5waHAvdm9kL2dldF9kZXRhaWw/dm9kX2lkPSR7aS52b2RfaWR9YCwKICAgICAgICAgICAgICAgIGRlc2M6IGkudm9kX3JlbWFya3MsCiAgICAgICAgICAgICAgICBwaWNfdXJsOiBpLnZvZF9waWMsCiAgICAgICAgICAgICAgICB2b2RfeWVhcjogaS52b2RfeWVhciwKICAgICAgICAgICAgICAgIHR5cGVfbmFtZTogdHlwZV9uYW1lCiAgICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdmlkZW9zOwogICAgfSwKICAgIAogICAg6aKE5aSE55CGOiBhc3luYyBmdW5jdGlvbiAoKSB7fSwKICAgIAogICAgY2xhc3NfcGFyc2U6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgdXJsID0gYCR7dGhpcy5ob3N0fS9hcGkucGhwL2luZGV4L2hvbWVgOwogICAgICAgIGxldCByZXNwID0gYXdhaXQgX2ZldGNoKHVybCwgeyBoZWFkZXJzOiB0aGlzLmhlYWRlcnMgfSk7CiAgICAgICAgbGV0IGpzb24gPSBKU09OLnBhcnNlKGF3YWl0IHJlc3AudGV4dCgpKTsKICAgICAgICBsZXQgY2F0ZWdvcmllcyA9IGpzb24uZGF0YS5jYXRlZ29yaWVzOwogICAgICAgIGxldCBjbGFzc2VzID0gW107CiAgICAgICAgZm9yIChjb25zdCBpIG9mIGNhdGVnb3JpZXMpIHsKICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHsKICAgICAgICAgICAgICAgIHR5cGVfaWQ6IGkudHlwZV9uYW1lLAogICAgICAgICAgICAgICAgdHlwZV9uYW1lOiBpLnR5cGVfbmFtZQogICAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsgY2xhc3M6IGNsYXNzZXMsIGZpbHRlcnM6IHt9IH07CiAgICB9LAogICAgCiAgICDmjqjojZA6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgdXJsID0gYCR7dGhpcy5ob3N0fS9hcGkucGhwL2luZGV4L2hvbWVgOwogICAgICAgIGxldCByZXNwID0gYXdhaXQgX2ZldGNoKHVybCwgeyBoZWFkZXJzOiB0aGlzLmhlYWRlcnMgfSk7CiAgICAgICAgbGV0IGpzb24gPSBKU09OLnBhcnNlKGF3YWl0IHJlc3AudGV4dCgpKTsKICAgICAgICBsZXQgY2F0ZWdvcmllcyA9IGpzb24uZGF0YS5jYXRlZ29yaWVzOwogICAgICAgIGxldCB2aWRlb3MgPSBbXTsKICAgICAgICBmb3IgKGNvbnN0IGkgb2YgY2F0ZWdvcmllcykgewogICAgICAgICAgICB2aWRlb3MucHVzaCguLi50aGlzLmpzb24ydm9kcyhpLnZpZGVvcykpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gc2V0UmVzdWx0KHZpZGVvcyk7CiAgICB9LAogICAgCiAgICDkuIDnuqc6IGFzeW5jIGZ1bmN0aW9uICh0aWQsIHBnLCBmaWx0ZXIsIGV4dGVuZCkgewogICAgICAgIGxldCB1cmwgPSBgJHt0aGlzLmhvc3R9L2FwaS5waHAvZmlsdGVyL3ZvZD90eXBlX25hbWU9JHtlbmNvZGVVUklDb21wb25lbnQodGlkKX0mcGFnZT0ke3BnfSZzb3J0PWhpdHNgOwogICAgICAgIGxldCByZXNwID0gYXdhaXQgX2ZldGNoKHVybCwgeyBoZWFkZXJzOiB0aGlzLmhlYWRlcnMgfSk7CiAgICAgICAgbGV0IGpzb24gPSBKU09OLnBhcnNlKGF3YWl0IHJlc3AudGV4dCgpKTsKICAgICAgICBsZXQgdmlkZW9zID0gdGhpcy5qc29uMnZvZHMoanNvbi5kYXRhKTsKICAgICAgICByZXR1cm4gc2V0UmVzdWx0KHZpZGVvcyk7CiAgICB9LAogICAgCiAgICDkuoznuqc6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgdm9kSWQgPSB0aGlzLmlucHV0Lm1hdGNoKC92b2RfaWQ9KFxkKykvKVsxXTsKICAgICAgICBsZXQgdXJsID0gYCR7dGhpcy5ob3N0fS9hcGkucGhwL3ZvZC9nZXRfZGV0YWlsP3ZvZF9pZD0ke3ZvZElkfWA7CiAgICAgICAgbGV0IHJlc3AgPSBhd2FpdCBfZmV0Y2godXJsLCB7IGhlYWRlcnM6IHRoaXMuaGVhZGVycyB9KTsKICAgICAgICBsZXQganNvbiA9IEpTT04ucGFyc2UoYXdhaXQgcmVzcC50ZXh0KCkpOwogICAgICAgIGxldCBkYXRhID0ganNvbi5kYXRhWzBdOwogICAgICAgIGxldCB2b2RwbGF5ZXIgPSBqc29uLnZvZHBsYXllcjsKICAgICAgICBsZXQgc2hvd3MgPSBbXTsKICAgICAgICBsZXQgcGxheV91cmxzID0gW107CiAgICAgICAgbGV0IHJhd19zaG93cyA9IGRhdGEudm9kX3BsYXlfZnJvbS5zcGxpdCgnJCQkJyk7CiAgICAgICAgbGV0IHJhd191cmxzX2xpc3QgPSBkYXRhLnZvZF9wbGF5X3VybC5zcGxpdCgnJCQkJyk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByYXdfc2hvd3MubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgbGV0IHNob3dfY29kZSA9IHJhd19zaG93c1tpXTsKICAgICAgICAgICAgbGV0IHVybHNfc3RyID0gcmF3X3VybHNfbGlzdFtpXTsKICAgICAgICAgICAgbGV0IG5lZWRfcGFyc2UgPSAwOwogICAgICAgICAgICBsZXQgaXNfc2hvdyA9IDA7CiAgICAgICAgICAgIGxldCBuYW1lID0gc2hvd19jb2RlOwogICAgICAgICAgICBmb3IgKGNvbnN0IHBsYXllciBvZiB2b2RwbGF5ZXIpIHsKICAgICAgICAgICAgICAgIGlmIChwbGF5ZXIuZnJvbSA9PT0gc2hvd19jb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgaXNfc2hvdyA9IDE7CiAgICAgICAgICAgICAgICAgICAgbmVlZF9wYXJzZSA9IHBsYXllci5kZWNvZGVfc3RhdHVzOwogICAgICAgICAgICAgICAgICAgIGlmIChzaG93X2NvZGUudG9Mb3dlckNhc2UoKSAhPT0gcGxheWVyLnNob3cudG9Mb3dlckNhc2UoKSkgewogICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gYCR7cGxheWVyLnNob3d9ICgke3Nob3dfY29kZX0pYDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICAgIGlmIChpc19zaG93ID09PSAxKSB7CiAgICAgICAgICAgICAgICBsZXQgdXJscyA9IFtdOwogICAgICAgICAgICAgICAgbGV0IGl0ZW1zID0gdXJsc19zdHIuc3BsaXQoJyMnKTsKICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykgewogICAgICAgICAgICAgICAgICAgIGlmIChpdGVtLmluY2x1ZGVzKCckJykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBhcnRzID0gaXRlbS5zcGxpdCgnJCcpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgZXBpc29kZSA9IHBhcnRzWzBdOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgbV91cmwgPSBwYXJ0c1sxXTsKICAgICAgICAgICAgICAgICAgICAgICAgdXJscy5wdXNoKGAke2VwaXNvZGV9JCR7c2hvd19jb2RlfUAke25lZWRfcGFyc2V9QCR7bV91cmx9YCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHVybHMubGVuZ3RoID4gMCkgewogICAgICAgICAgICAgICAgICAgIHBsYXlfdXJscy5wdXNoKHVybHMuam9pbignIycpKTsKICAgICAgICAgICAgICAgICAgICBzaG93cy5wdXNoKG5hbWUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIAogICAgICAgIGxldCBWT0QgPSB7CiAgICAgICAgICAgIHZvZF9pZDogZGF0YS52b2RfaWQudG9TdHJpbmcoKSwKICAgICAgICAgICAgdm9kX25hbWU6IGRhdGEudm9kX25hbWUsCiAgICAgICAgICAgIHZvZF9waWM6IGRhdGEudm9kX3BpYywKICAgICAgICAgICAgdm9kX3JlbWFya3M6IGRhdGEudm9kX3JlbWFya3MsCiAgICAgICAgICAgIHZvZF95ZWFyOiBkYXRhLnZvZF95ZWFyLAogICAgICAgICAgICB2b2RfYXJlYTogZGF0YS52b2RfYXJlYSwKICAgICAgICAgICAgdm9kX2FjdG9yOiBkYXRhLnZvZF9hY3RvciwKICAgICAgICAgICAgdm9kX2RpcmVjdG9yOiBkYXRhLnZvZF9kaXJlY3RvciwKICAgICAgICAgICAgdm9kX2NvbnRlbnQ6IGRhdGEudm9kX2NvbnRlbnQsCiAgICAgICAgICAgIHZvZF9wbGF5X2Zyb206IHNob3dzLmpvaW4oJyQkJCcpLAogICAgICAgICAgICB2b2RfcGxheV91cmw6IHBsYXlfdXJscy5qb2luKCckJCQnKSwKICAgICAgICAgICAgdHlwZV9uYW1lOiBkYXRhLnZvZF9jbGFzcwogICAgICAgIH07CiAgICAgICAgcmV0dXJuIFZPRDsKICAgIH0sCiAgICAKICAgIOaQnOe0ojogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGxldCB1cmwgPSBgJHt0aGlzLmhvc3R9L2FwaS5waHAvc2VhcmNoL2luZGV4P3dkPSR7ZW5jb2RlVVJJQ29tcG9uZW50KHRoaXMuS0VZKX0mcGFnZT0ke3RoaXMuTVlfUEFHRX0mbGltaXQ9MTVgOwogICAgICAgIGxldCByZXNwID0gYXdhaXQgX2ZldGNoKHVybCwgeyBoZWFkZXJzOiB0aGlzLmhlYWRlcnMgfSk7CiAgICAgICAgbGV0IGpzb24gPSBKU09OLnBhcnNlKGF3YWl0IHJlc3AudGV4dCgpKTsKICAgICAgICBsZXQgdmlkZW9zID0gdGhpcy5qc29uMnZvZHMoanNvbi5kYXRhKTsKICAgICAgICByZXR1cm4gc2V0UmVzdWx0KHZpZGVvcyk7CiAgICB9LAogICAgCiAgICBsYXp5OiBhc3luYyBmdW5jdGlvbiAoKSB7CiAgICAgICAgbGV0IFtwbGF5X2Zyb20sIG5lZWRfcGFyc2UsIHJhd191cmxdID0gdGhpcy5pbnB1dC5zcGxpdCgnQCcpOwogICAgICAgIGxldCBqeCA9IDA7CiAgICAgICAgbGV0IGZpbmFsX3VybCA9ICcnOwogICAgICAgIGlmIChuZWVkX3BhcnNlID09PSAnMScpIHsKICAgICAgICAgICAgbGV0IGF1dGhfdG9rZW4gPSAnJzsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAyOyBpKyspIHsKICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IGFwaVVybCA9IGAke3RoaXMuaG9zdH0vYXBpLnBocC9kZWNvZGUvdXJsLz91cmw9JHtlbmNvZGVVUklDb21wb25lbnQocmF3X3VybCl9JnZvZEZyb209JHtwbGF5X2Zyb219JHthdXRoX3Rva2VufWA7CiAgICAgICAgICAgICAgICAgICAgbGV0IHJlc3AgPSBhd2FpdCBfZmV0Y2goYXBpVXJsLCB7IGhlYWRlcnM6IHRoaXMuaGVhZGVycyB9KTsKICAgICAgICAgICAgICAgIGxldCBqc29uID0gSlNPTi5wYXJzZShhd2FpdCByZXNwLnRleHQoKSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGpzb24uY29kZSA9PT0gMiAmJiBqc29uLmNoYWxsZW5nZSkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgdG9rZW4gPSBldmFsKGpzb24uY2hhbGxlbmdlKTsKICAgICAgICAgICAgICAgICAgICAgICAgYXV0aF90b2tlbiA9IGAmdG9rZW49JHt0b2tlbn1gOwogICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgbGV0IHBsYXlfdXJsID0ganNvbi5kYXRhOwogICAgICAgICAgICAgICAgICAgIGlmIChwbGF5X3VybCAmJiBwbGF5X3VybC5zdGFydHNXaXRoKCdodHRwJykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZmluYWxfdXJsID0gcGxheV91cmw7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIAogICAgICAgIGlmICghZmluYWxfdXJsKSB7CiAgICAgICAgICAgIGZpbmFsX3VybCA9IHJhd191cmw7CiAgICAgICAgICAgIGlmICgvKD86d3d3XC5pcWl5aXx2XC5xcXx2XC55b3VrdXx3d3dcLm1ndHZ8d3d3XC5iaWxpYmlsaSlcLmNvbS8udGVzdChyYXdfdXJsKSkgewogICAgICAgICAgICAgICAganggPSAxOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIHBhcnNlOiBqeCwKICAgICAgICAgICAgdXJsOiBmaW5hbF91cmwsCiAgICAgICAgICAgIGhlYWRlcjogeyAnVXNlci1BZ2VudCc6IHRoaXMuaGVhZGVyc1snVXNlci1BZ2VudCddIH0KICAgICAgICB9OwogICAgfQp9Ow== \ No newline at end of file diff --git "a/spider/js/\346\242\250\345\233\255\350\241\214[\346\210\217].js" "b/spider/js/\346\242\250\345\233\255\350\241\214[\346\210\217].js" index 22af9d45..7204c5db 100644 --- "a/spider/js/\346\242\250\345\233\255\350\241\214[\346\210\217].js" +++ "b/spider/js/\346\242\250\345\233\255\350\241\214[\346\210\217].js" @@ -11,251 +11,4 @@ }) */ -var rule = { - 类型: '影视', - author: 'EylinSir', - title: '梨园行戏曲', - desc: '梨园行戏曲源', - host: 'https://fly.daoran.tv', - homeUrl: 'https://fly.daoran.tv', - url: '/API_ROP/search/album/screen', - searchUrl: '/API_ROP/search/album/list?keyword=**', - logo: 'https://img.znds.com//uploads/new/221222/9-2212221050561N.png', - searchable: 1, - quickSearch: 0, - filterable: 1, - timeout: 10000, - play_parse: true, - headers: { - 'md5': 'SkvyrWqK9QHTdCT12Rhxunjx+WwMTe9y4KwgeASFDhbYabRSPskR0Q==', - 'Content-Type': 'application/json; charset=UTF-8', - 'User-Agent': 'okhttp/3.12.10', - 'Host': 'fly.daoran.tv', - 'Connection': 'Keep-Alive' - }, - - request: async function (url, obj) { - obj = obj || {}; - let response = await _fetch(url, { - method: obj.method || 'POST', - headers: obj.headers || this.headers, - body: obj.data ? JSON.stringify(obj.data) : undefined - }); - return response.text(); - }, - - _format_img: function (img) { - if (!img) { - return ''; - } - if (!img.startsWith('http')) { - return `https://ottphoto.daoran.tv/HD/${img}`; - } - return img; - }, - - 预处理: async function () {}, - - class_parse: async function () { - let cate_list = [ - {"n": "全部", "v": ""}, - {"n": "黄梅戏", "v": "hmx"}, {"n": "京剧", "v": "jingju"}, {"n": "曲剧", "v": "quju"}, - {"n": "秦腔", "v": "qinq"}, {"n": "潮剧", "v": "chaoju"}, {"n": "沪剧", "v": "huju"}, - {"n": "昆曲", "v": "kunqu"}, {"n": "淮剧", "v": "huaiju"}, {"n": "婺剧", "v": "wuju"}, - {"n": "河南大鼓书", "v": "hndgs"}, {"n": "滇剧", "v": "dianju"}, {"n": "老年大学", "v": "WK"}, - {"n": "绍剧", "v": "shaojv"}, {"n": "曲艺晚会", "v": "else"}, {"n": "皮影戏", "v": "pyx"}, - {"n": "四平调", "v": "spd"}, {"n": "吕剧", "v": "lvjv"}, {"n": "柳琴戏", "v": "liuqx"}, - {"n": "莆仙戏", "v": "pxx"}, {"n": "宛梆", "v": "wb"}, {"n": "锡剧", "v": "xiju"}, - {"n": "大平调", "v": "dpd"}, {"n": "话剧", "v": "huaju"}, {"n": "西秦戏", "v": "xqx"}, - {"n": "川剧", "v": "chuanju"}, {"n": "赣剧", "v": "tagId"}, {"n": "太康道情", "v": "tkdq"}, - {"n": "闽剧", "v": "minju"}, {"n": "梅花大鼓", "v": "mhdg"}, {"n": "吉剧", "v": "jiju"}, - {"n": "白字戏", "v": "bzx"}, {"n": "豫剧", "v": "yuju"}, {"n": "越剧", "v": "yueju"}, - {"n": "评剧", "v": "pingju"}, {"n": "坠子", "v": "hnzz"}, {"n": "河北梆子", "v": "hbbz"}, - {"n": "粤剧", "v": "gddx"}, {"n": "二夹弦", "v": "ejx"}, {"n": "河南琴书", "v": "hnqs"}, - {"n": "戏曲", "v": "xq"}, {"n": "二人台", "v": "ERT"}, {"n": "越调", "v": "yued"}, - {"n": "乐腔", "v": "lq"}, {"n": "扬剧", "v": "yangju"}, {"n": "京韵大鼓", "v": "jydg"}, - {"n": "彩调", "v": "caidiao"}, {"n": "琼剧", "v": "qiongju"}, {"n": "蒲剧", "v": "pujv"}, - {"n": "西河大鼓", "v": "xhdg"}, {"n": "湘剧", "v": "xj"}, {"n": "麦田乡韾", "v": "mtxy"}, - {"n": "评书", "v": "pingshu"}, {"n": "庐剧", "v": "luju"}, {"n": "单弦", "v": "danxian"}, - {"n": "花鼓戏", "v": "huagx"}, {"n": "相声", "v": "xiang"}, {"n": "四股弦", "v": "sgx"}, - {"n": "保定老调", "v": "bdld"}, {"n": "晋剧", "v": "jinju"}, {"n": "其他", "v": "other"}, - {"n": "正字戏", "v": "zzx"}, {"n": "楚剧", "v": "chuju"} - ]; - - return { - class: [{ 'type_name': '戏曲片库', 'type_id': 'all' }], - filters: { - "all": [ - {"key": "sect", "name": "曲种", "value": cate_list}, - {"key": "area", "name": "资费", "value": [{"n": "全部", "v": "0"}, {"n": "免费", "v": "1"}, {"n": "VIP", "v": "2"}]}, - {"key": "sort", "name": "排序", "value": [{"n": "最热", "v": "hot"}, {"n": "最新", "v": "online"}]} - ] - } - }; - }, - - 推荐: async function () { - return await this.一级('all', 1, {}, {}); - }, - - 一级: async function (tid, pg, filter, extend) { - let url = `${this.host}/API_ROP/search/album/screen`; - let sect = extend?.sect || ''; - if (tid === 'all' && !sect) { - sect = ''; - } - - let payload = { - "cur": parseInt(pg), - "pageSize": 30, - "resType": 1, - "sect": sect, - "orderby": extend?.sort || 'hot', - "tagId": 0, - "userId": "92315ec6e58a45ba7f47fd143b3d7956", - "channel": "vivo", - "item": "y9", - "nodeCode": "001000", - "project": "lyhxcx" - }; - - let area = extend?.area || '0'; - if (area === '1' || area === '2') { - payload['free'] = parseInt(area); - } - - try { - let resp = await this.request(url, { data: payload }); - let json = JSON.parse(resp); - let data = json.pb || json.data || {}; - let vod_list = []; - for (let item of data.dataList || []) { - vod_list.push({ - title: item.name, - url: `${this.host}/API_ROP/album/res/list?albumCode=${item.code}`, - desc: (item.publishTime || '').split(' ')[0], - pic_url: this._format_img(item.imgsec), - vod_year: (item.publishTime || '').substring(0, 4) - }); - } - - return setResult(vod_list); - } catch (e) { - console.error(e); - return setResult([]); - } - }, - - 二级: async function () { - let albumCode = this.input.match(/albumCode=(.*?)(?:&|$)/)[1]; - let url = `${this.host}/API_ROP/album/res/list`; - - let payload = { - "albumCode": albumCode, - "cur": 1, - "pageSize": 500, - "userId": "92315ec6e58a45ba7f47fd143b3d7956", - "channel": "vivo", - "item": "y9", - "nodeCode": "001000", - "project": "lyhxcx" - }; - - try { - let resp = await this.request(url, { data: payload }); - let json = JSON.parse(resp); - let album = json.album || {}; - let tracks = json.pb?.dataList || []; - tracks.sort((a, b) => parseInt(a.sort || 0) - parseInt(b.sort || 0)); - let play_urls = []; - for (let t of tracks) { - if (t.code) { - play_urls.push(`${t.name.replace(/\$/g, '_')}$${t.code}`); - } - } - - let VOD = { - vod_id: albumCode, - vod_name: album.name || '未知', - vod_pic: this._format_img(album.imgsec), - type_name: "戏曲", - vod_year: album.publishTime || '', - vod_area: "中国", - vod_content: album.des || '暂无简介', - vod_play_from: "梨园行", - vod_play_url: play_urls.join('#') - }; - - return VOD; - } catch (e) { - console.error(e); - return {}; - } - }, - - 搜索: async function () { - let url = `${this.host}/API_ROP/search/album/list`; - let payload = { - "cur": parseInt(this.MY_PAGE), - "pageSize": 20, - "keyword": this.KEY, - "item": "y9", - "nodeCode": "001000", - "orderby": "hot", - "px": 2, - "sect": [], - "userId": "92315ec6e58a45ba7f47fd143b3d7956", - "project": "lyhxcx" - }; - - try { - let resp = await this.request(url, { data: payload }); - let json = JSON.parse(resp); - let data = json.pb || json.data || {}; - let vod_list = []; - for (let item of data.dataList || []) { - vod_list.push({ - title: item.name, - url: `${this.host}/API_ROP/album/res/list?albumCode=${item.code}`, - desc: (item.publishTime || ''), - pic_url: this._format_img(item.imgsec) - }); - } - return setResult(vod_list); - } catch (e) { - console.error(e); - return setResult([]); - } - }, - - lazy: async function () { - let resCode = this.input; - let url = `${this.host}/API_ROP/play/get/playurl`; - let payload = { - "resCode": resCode, - "item": "y9", - "mask": 0, - "nodeCode": "001000", - "project": "lyhxcx", - "px": 2, - "userId": "92315ec6e58a45ba7f47fd143b3d7956" - }; - - try { - let resp = await this.request(url, { data: payload }); - let json = JSON.parse(resp); - let play_url = json.playres?.playurl || ''; - return { - parse: 0, - url: play_url, - header: { 'User-Agent': this.headers['User-Agent'] } - }; - } catch (e) { - console.error(e); - return { - parse: 0, - url: '' - }; - } - } -}; \ No newline at end of file +dmFyIHJ1bGUgPSB7CiAgICDnsbvlnos6ICflvbHop4YnLAogICAgYXV0aG9yOiAnRXlsaW5TaXInLAogICAgdGl0bGU6ICfmoqjlm63ooYzmiI/mm7InLAogICAgZGVzYzogJ+aiqOWbreihjOaIj+absua6kCcsCiAgICBob3N0OiAnaHR0cHM6Ly9mbHkuZGFvcmFuLnR2JywKICAgIGhvbWVVcmw6ICdodHRwczovL2ZseS5kYW9yYW4udHYnLAogICAgdXJsOiAnL0FQSV9ST1Avc2VhcmNoL2FsYnVtL3NjcmVlbicsCiAgICBzZWFyY2hVcmw6ICcvQVBJX1JPUC9zZWFyY2gvYWxidW0vbGlzdD9rZXl3b3JkPSoqJywKICAgIGxvZ286ICdodHRwczovL2ltZy56bmRzLmNvbS8vdXBsb2Fkcy9uZXcvMjIxMjIyLzktMjIxMjIyMTA1MDU2MU4ucG5nJywKICAgIHNlYXJjaGFibGU6IDEsCiAgICBxdWlja1NlYXJjaDogMCwKICAgIGZpbHRlcmFibGU6IDEsCiAgICB0aW1lb3V0OiAxMDAwMCwKICAgIHBsYXlfcGFyc2U6IHRydWUsCiAgICBoZWFkZXJzOiB7CiAgICAgICAgJ21kNSc6ICdTa3Z5cldxSzlRSFRkQ1QxMlJoeHVuangrV3dNVGU5eTRLd2dlQVNGRGhiWWFiUlNQc2tSMFE9PScsCiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uOyBjaGFyc2V0PVVURi04JywKICAgICAgICAnVXNlci1BZ2VudCc6ICdva2h0dHAvMy4xMi4xMCcsCiAgICAgICAgJ0hvc3QnOiAnZmx5LmRhb3Jhbi50dicsCiAgICAgICAgJ0Nvbm5lY3Rpb24nOiAnS2VlcC1BbGl2ZScKICAgIH0sCiAgICAKICAgIHJlcXVlc3Q6IGFzeW5jIGZ1bmN0aW9uICh1cmwsIG9iaikgewogICAgICAgIG9iaiA9IG9iaiB8fCB7fTsKICAgICAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCBfZmV0Y2godXJsLCB7CiAgICAgICAgICAgIG1ldGhvZDogb2JqLm1ldGhvZCB8fCAnUE9TVCcsCiAgICAgICAgICAgIGhlYWRlcnM6IG9iai5oZWFkZXJzIHx8IHRoaXMuaGVhZGVycywKICAgICAgICAgICAgYm9keTogb2JqLmRhdGEgPyBKU09OLnN0cmluZ2lmeShvYmouZGF0YSkgOiB1bmRlZmluZWQKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpOwogICAgfSwKCiAgICBfZm9ybWF0X2ltZzogZnVuY3Rpb24gKGltZykgewogICAgICAgIGlmICghaW1nKSB7CiAgICAgICAgICAgIHJldHVybiAnJzsKICAgICAgICB9CiAgICAgICAgaWYgKCFpbWcuc3RhcnRzV2l0aCgnaHR0cCcpKSB7CiAgICAgICAgICAgIHJldHVybiBgaHR0cHM6Ly9vdHRwaG90by5kYW9yYW4udHYvSEQvJHtpbWd9YDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGltZzsKICAgIH0sCiAgICAKICAgIOmihOWkhOeQhjogYXN5bmMgZnVuY3Rpb24gKCkge30sCiAgICAKICAgIGNsYXNzX3BhcnNlOiBhc3luYyBmdW5jdGlvbiAoKSB7CiAgICAgICAgbGV0IGNhdGVfbGlzdCA9IFsKICAgICAgICAgICAgeyJuIjogIuWFqOmDqCIsICJ2IjogIiJ9LAogICAgICAgICAgICB7Im4iOiAi6buE5qKF5oiPIiwgInYiOiAiaG14In0sIHsibiI6ICLkuqzliaciLCAidiI6ICJqaW5nanUifSwgeyJuIjogIuabsuWJpyIsICJ2IjogInF1anUifSwKICAgICAgICAgICAgeyJuIjogIuenpuiFlCIsICJ2IjogInFpbnEifSwgeyJuIjogIua9ruWJpyIsICJ2IjogImNoYW9qdSJ9LCB7Im4iOiAi5rKq5YmnIiwgInYiOiAiaHVqdSJ9LAogICAgICAgICAgICB7Im4iOiAi5piG5puyIiwgInYiOiAia3VucXUifSwgeyJuIjogIua3ruWJpyIsICJ2IjogImh1YWlqdSJ9LCB7Im4iOiAi5am65YmnIiwgInYiOiAid3VqdSJ9LAogICAgICAgICAgICB7Im4iOiAi5rKz5Y2X5aSn6byT5LmmIiwgInYiOiAiaG5kZ3MifSwgeyJuIjogIua7h+WJpyIsICJ2IjogImRpYW5qdSJ9LCB7Im4iOiAi6ICB5bm05aSn5a2mIiwgInYiOiAiV0sifSwKICAgICAgICAgICAgeyJuIjogIue7jeWJpyIsICJ2IjogInNoYW9qdiJ9LCB7Im4iOiAi5puy6Im65pma5LyaIiwgInYiOiAiZWxzZSJ9LCB7Im4iOiAi55qu5b2x5oiPIiwgInYiOiAicHl4In0sCiAgICAgICAgICAgIHsibiI6ICLlm5vlubPosIMiLCAidiI6ICJzcGQifSwgeyJuIjogIuWQleWJpyIsICJ2IjogImx2anYifSwgeyJuIjogIuafs+eQtOaIjyIsICJ2IjogImxpdXF4In0sCiAgICAgICAgICAgIHsibiI6ICLojobku5nmiI8iLCAidiI6ICJweHgifSwgeyJuIjogIuWum+aihiIsICJ2IjogIndiIn0sIHsibiI6ICLplKHliaciLCAidiI6ICJ4aWp1In0sCiAgICAgICAgICAgIHsibiI6ICLlpKflubPosIMiLCAidiI6ICJkcGQifSwgeyJuIjogIuivneWJpyIsICJ2IjogImh1YWp1In0sIHsibiI6ICLopb/np6bmiI8iLCAidiI6ICJ4cXgifSwKICAgICAgICAgICAgeyJuIjogIuW3neWJpyIsICJ2IjogImNodWFuanUifSwgeyJuIjogIui1o+WJpyIsICJ2IjogInRhZ0lkIn0sIHsibiI6ICLlpKrlurfpgZPmg4UiLCAidiI6ICJ0a2RxIn0sCiAgICAgICAgICAgIHsibiI6ICLpl73liaciLCAidiI6ICJtaW5qdSJ9LCB7Im4iOiAi5qKF6Iqx5aSn6byTIiwgInYiOiAibWhkZyJ9LCB7Im4iOiAi5ZCJ5YmnIiwgInYiOiAiamlqdSJ9LAogICAgICAgICAgICB7Im4iOiAi55m95a2X5oiPIiwgInYiOiAiYnp4In0sIHsibiI6ICLosavliaciLCAidiI6ICJ5dWp1In0sIHsibiI6ICLotorliaciLCAidiI6ICJ5dWVqdSJ9LAogICAgICAgICAgICB7Im4iOiAi6K+E5YmnIiwgInYiOiAicGluZ2p1In0sIHsibiI6ICLlnaDlrZAiLCAidiI6ICJobnp6In0sIHsibiI6ICLmsrPljJfmooblrZAiLCAidiI6ICJoYmJ6In0sCiAgICAgICAgICAgIHsibiI6ICLnsqTliaciLCAidiI6ICJnZGR4In0sIHsibiI6ICLkuozlpLnlvKYiLCAidiI6ICJlangifSwgeyJuIjogIuays+WNl+eQtOS5piIsICJ2IjogImhucXMifSwKICAgICAgICAgICAgeyJuIjogIuaIj+absiIsICJ2IjogInhxIn0sIHsibiI6ICLkuozkurrlj7AiLCAidiI6ICJFUlQifSwgeyJuIjogIui2iuiwgyIsICJ2IjogInl1ZWQifSwKICAgICAgICAgICAgeyJuIjogIuS5kOiFlCIsICJ2IjogImxxIn0sIHsibiI6ICLmiazliaciLCAidiI6ICJ5YW5nanUifSwgeyJuIjogIuS6rOmfteWkp+m8kyIsICJ2IjogImp5ZGcifSwKICAgICAgICAgICAgeyJuIjogIuW9qeiwgyIsICJ2IjogImNhaWRpYW8ifSwgeyJuIjogIueQvOWJpyIsICJ2IjogInFpb25nanUifSwgeyJuIjogIuiSsuWJpyIsICJ2IjogInB1anYifSwKICAgICAgICAgICAgeyJuIjogIuilv+ays+Wkp+m8kyIsICJ2IjogInhoZGcifSwgeyJuIjogIua5mOWJpyIsICJ2IjogInhqIn0sIHsibiI6ICLpuqbnlLDkuaHpn74iLCAidiI6ICJtdHh5In0sCiAgICAgICAgICAgIHsibiI6ICLor4TkuaYiLCAidiI6ICJwaW5nc2h1In0sIHsibiI6ICLlupDliaciLCAidiI6ICJsdWp1In0sIHsibiI6ICLljZXlvKYiLCAidiI6ICJkYW54aWFuIn0sCiAgICAgICAgICAgIHsibiI6ICLoirHpvJPmiI8iLCAidiI6ICJodWFneCJ9LCB7Im4iOiAi55u45aOwIiwgInYiOiAieGlhbmcifSwgeyJuIjogIuWbm+iCoeW8piIsICJ2IjogInNneCJ9LAogICAgICAgICAgICB7Im4iOiAi5L+d5a6a6ICB6LCDIiwgInYiOiAiYmRsZCJ9LCB7Im4iOiAi5pmL5YmnIiwgInYiOiAiamluanUifSwgeyJuIjogIuWFtuS7liIsICJ2IjogIm90aGVyIn0sCiAgICAgICAgICAgIHsibiI6ICLmraPlrZfmiI8iLCAidiI6ICJ6engifSwgeyJuIjogIualmuWJpyIsICJ2IjogImNodWp1In0KICAgICAgICBdOwogICAgICAgIAogICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIGNsYXNzOiBbeyAndHlwZV9uYW1lJzogJ+aIj+absueJh+W6kycsICd0eXBlX2lkJzogJ2FsbCcgfV0sCiAgICAgICAgICAgIGZpbHRlcnM6IHsKICAgICAgICAgICAgICAgICJhbGwiOiBbCiAgICAgICAgICAgICAgICAgICAgeyJrZXkiOiAic2VjdCIsICJuYW1lIjogIuabsuenjSIsICJ2YWx1ZSI6IGNhdGVfbGlzdH0sCiAgICAgICAgICAgICAgICAgICAgeyJrZXkiOiAiYXJlYSIsICJuYW1lIjogIui1hOi0uSIsICJ2YWx1ZSI6IFt7Im4iOiAi5YWo6YOoIiwgInYiOiAiMCJ9LCB7Im4iOiAi5YWN6LS5IiwgInYiOiAiMSJ9LCB7Im4iOiAiVklQIiwgInYiOiAiMiJ9XX0sCiAgICAgICAgICAgICAgICAgICAgeyJrZXkiOiAic29ydCIsICJuYW1lIjogIuaOkuW6jyIsICJ2YWx1ZSI6IFt7Im4iOiAi5pyA54OtIiwgInYiOiAiaG90In0sIHsibiI6ICLmnIDmlrAiLCAidiI6ICJvbmxpbmUifV19CiAgICAgICAgICAgICAgICBdCiAgICAgICAgICAgIH0KICAgICAgICB9OwogICAgfSwKICAgIAogICAg5o6o6I2QOiBhc3luYyBmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMu5LiA57qnKCdhbGwnLCAxLCB7fSwge30pOwogICAgfSwKICAgIAogICAg5LiA57qnOiBhc3luYyBmdW5jdGlvbiAodGlkLCBwZywgZmlsdGVyLCBleHRlbmQpIHsKICAgICAgICBsZXQgdXJsID0gYCR7dGhpcy5ob3N0fS9BUElfUk9QL3NlYXJjaC9hbGJ1bS9zY3JlZW5gOwogICAgICAgIGxldCBzZWN0ID0gZXh0ZW5kPy5zZWN0IHx8ICcnOwogICAgICAgIGlmICh0aWQgPT09ICdhbGwnICYmICFzZWN0KSB7CiAgICAgICAgICAgIHNlY3QgPSAnJzsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgbGV0IHBheWxvYWQgPSB7CiAgICAgICAgICAgICJjdXIiOiBwYXJzZUludChwZyksCiAgICAgICAgICAgICJwYWdlU2l6ZSI6IDMwLAogICAgICAgICAgICAicmVzVHlwZSI6IDEsCiAgICAgICAgICAgICJzZWN0Ijogc2VjdCwKICAgICAgICAgICAgIm9yZGVyYnkiOiBleHRlbmQ/LnNvcnQgfHwgJ2hvdCcsCiAgICAgICAgICAgICJ0YWdJZCI6IDAsCiAgICAgICAgICAgICJ1c2VySWQiOiAiOTIzMTVlYzZlNThhNDViYTdmNDdmZDE0M2IzZDc5NTYiLAogICAgICAgICAgICAiY2hhbm5lbCI6ICJ2aXZvIiwKICAgICAgICAgICAgIml0ZW0iOiAieTkiLAogICAgICAgICAgICAibm9kZUNvZGUiOiAiMDAxMDAwIiwKICAgICAgICAgICAgInByb2plY3QiOiAibHloeGN4IgogICAgICAgIH07CiAgICAgICAgCiAgICAgICAgbGV0IGFyZWEgPSBleHRlbmQ/LmFyZWEgfHwgJzAnOwogICAgICAgIGlmIChhcmVhID09PSAnMScgfHwgYXJlYSA9PT0gJzInKSB7CiAgICAgICAgICAgIHBheWxvYWRbJ2ZyZWUnXSA9IHBhcnNlSW50KGFyZWEpOwogICAgICAgIH0KICAgICAgICAKICAgICAgICB0cnkgewogICAgICAgICAgICBsZXQgcmVzcCA9IGF3YWl0IHRoaXMucmVxdWVzdCh1cmwsIHsgZGF0YTogcGF5bG9hZCB9KTsKICAgICAgICAgICAgbGV0IGpzb24gPSBKU09OLnBhcnNlKHJlc3ApOwogICAgICAgICAgICBsZXQgZGF0YSA9IGpzb24ucGIgfHwganNvbi5kYXRhIHx8IHt9OwogICAgICAgICAgICBsZXQgdm9kX2xpc3QgPSBbXTsKICAgICAgICAgICAgZm9yIChsZXQgaXRlbSBvZiBkYXRhLmRhdGFMaXN0IHx8IFtdKSB7CiAgICAgICAgICAgICAgICB2b2RfbGlzdC5wdXNoKHsKICAgICAgICAgICAgICAgICAgICB0aXRsZTogaXRlbS5uYW1lLAogICAgICAgICAgICAgICAgICAgIHVybDogYCR7dGhpcy5ob3N0fS9BUElfUk9QL2FsYnVtL3Jlcy9saXN0P2FsYnVtQ29kZT0ke2l0ZW0uY29kZX1gLAogICAgICAgICAgICAgICAgICAgIGRlc2M6IChpdGVtLnB1Ymxpc2hUaW1lIHx8ICcnKS5zcGxpdCgnICcpWzBdLAogICAgICAgICAgICAgICAgICAgIHBpY191cmw6IHRoaXMuX2Zvcm1hdF9pbWcoaXRlbS5pbWdzZWMpLAogICAgICAgICAgICAgICAgICAgIHZvZF95ZWFyOiAoaXRlbS5wdWJsaXNoVGltZSB8fCAnJykuc3Vic3RyaW5nKDAsIDQpCiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgICAKICAgICAgICAgICAgcmV0dXJuIHNldFJlc3VsdCh2b2RfbGlzdCk7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpOwogICAgICAgICAgICByZXR1cm4gc2V0UmVzdWx0KFtdKTsKICAgICAgICB9CiAgICB9LAogICAgCiAgICDkuoznuqc6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgYWxidW1Db2RlID0gdGhpcy5pbnB1dC5tYXRjaCgvYWxidW1Db2RlPSguKj8pKD86JnwkKS8pWzFdOwogICAgICAgIGxldCB1cmwgPSBgJHt0aGlzLmhvc3R9L0FQSV9ST1AvYWxidW0vcmVzL2xpc3RgOwogICAgICAgIAogICAgICAgIGxldCBwYXlsb2FkID0gewogICAgICAgICAgICAiYWxidW1Db2RlIjogYWxidW1Db2RlLAogICAgICAgICAgICAiY3VyIjogMSwKICAgICAgICAgICAgInBhZ2VTaXplIjogNTAwLAogICAgICAgICAgICAidXNlcklkIjogIjkyMzE1ZWM2ZTU4YTQ1YmE3ZjQ3ZmQxNDNiM2Q3OTU2IiwKICAgICAgICAgICAgImNoYW5uZWwiOiAidml2byIsCiAgICAgICAgICAgICJpdGVtIjogInk5IiwKICAgICAgICAgICAgIm5vZGVDb2RlIjogIjAwMTAwMCIsCiAgICAgICAgICAgICJwcm9qZWN0IjogImx5aHhjeCIKICAgICAgICB9OwogICAgICAgIAogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGxldCByZXNwID0gYXdhaXQgdGhpcy5yZXF1ZXN0KHVybCwgeyBkYXRhOiBwYXlsb2FkIH0pOwogICAgICAgICAgICBsZXQganNvbiA9IEpTT04ucGFyc2UocmVzcCk7CiAgICAgICAgICAgIGxldCBhbGJ1bSA9IGpzb24uYWxidW0gfHwge307CiAgICAgICAgICAgIGxldCB0cmFja3MgPSBqc29uLnBiPy5kYXRhTGlzdCB8fCBbXTsKICAgICAgICAgICAgdHJhY2tzLnNvcnQoKGEsIGIpID0+IHBhcnNlSW50KGEuc29ydCB8fCAwKSAtIHBhcnNlSW50KGIuc29ydCB8fCAwKSk7CiAgICAgICAgICAgIGxldCBwbGF5X3VybHMgPSBbXTsKICAgICAgICAgICAgZm9yIChsZXQgdCBvZiB0cmFja3MpIHsKICAgICAgICAgICAgICAgIGlmICh0LmNvZGUpIHsKICAgICAgICAgICAgICAgICAgICBwbGF5X3VybHMucHVzaChgJHt0Lm5hbWUucmVwbGFjZSgvXCQvZywgJ18nKX0kJHt0LmNvZGV9YCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICAgIGxldCBWT0QgPSB7CiAgICAgICAgICAgICAgICB2b2RfaWQ6IGFsYnVtQ29kZSwKICAgICAgICAgICAgICAgIHZvZF9uYW1lOiBhbGJ1bS5uYW1lIHx8ICfmnKrnn6UnLAogICAgICAgICAgICAgICAgdm9kX3BpYzogdGhpcy5fZm9ybWF0X2ltZyhhbGJ1bS5pbWdzZWMpLAogICAgICAgICAgICAgICAgdHlwZV9uYW1lOiAi5oiP5puyIiwKICAgICAgICAgICAgICAgIHZvZF95ZWFyOiBhbGJ1bS5wdWJsaXNoVGltZSB8fCAnJywKICAgICAgICAgICAgICAgIHZvZF9hcmVhOiAi5Lit5Zu9IiwKICAgICAgICAgICAgICAgIHZvZF9jb250ZW50OiBhbGJ1bS5kZXMgfHwgJ+aaguaXoOeugOS7iycsCiAgICAgICAgICAgICAgICB2b2RfcGxheV9mcm9tOiAi5qKo5Zut6KGMIiwKICAgICAgICAgICAgICAgIHZvZF9wbGF5X3VybDogcGxheV91cmxzLmpvaW4oJyMnKQogICAgICAgICAgICB9OwogICAgICAgICAgICAKICAgICAgICAgICAgcmV0dXJuIFZPRDsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7CiAgICAgICAgICAgIHJldHVybiB7fTsKICAgICAgICB9CiAgICB9LAogICAgCiAgICDmkJzntKI6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgdXJsID0gYCR7dGhpcy5ob3N0fS9BUElfUk9QL3NlYXJjaC9hbGJ1bS9saXN0YDsKICAgICAgICBsZXQgcGF5bG9hZCA9IHsKICAgICAgICAgICAgImN1ciI6IHBhcnNlSW50KHRoaXMuTVlfUEFHRSksCiAgICAgICAgICAgICJwYWdlU2l6ZSI6IDIwLAogICAgICAgICAgICAia2V5d29yZCI6IHRoaXMuS0VZLAogICAgICAgICAgICAiaXRlbSI6ICJ5OSIsCiAgICAgICAgICAgICJub2RlQ29kZSI6ICIwMDEwMDAiLAogICAgICAgICAgICAib3JkZXJieSI6ICJob3QiLAogICAgICAgICAgICAicHgiOiAyLAogICAgICAgICAgICAic2VjdCI6IFtdLAogICAgICAgICAgICAidXNlcklkIjogIjkyMzE1ZWM2ZTU4YTQ1YmE3ZjQ3ZmQxNDNiM2Q3OTU2IiwKICAgICAgICAgICAgInByb2plY3QiOiAibHloeGN4IgogICAgICAgIH07CiAgICAgICAgCiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgbGV0IHJlc3AgPSBhd2FpdCB0aGlzLnJlcXVlc3QodXJsLCB7IGRhdGE6IHBheWxvYWQgfSk7CiAgICAgICAgICAgIGxldCBqc29uID0gSlNPTi5wYXJzZShyZXNwKTsKICAgICAgICAgICAgbGV0IGRhdGEgPSBqc29uLnBiIHx8IGpzb24uZGF0YSB8fCB7fTsKICAgICAgICAgICAgbGV0IHZvZF9saXN0ID0gW107CiAgICAgICAgICAgIGZvciAobGV0IGl0ZW0gb2YgZGF0YS5kYXRhTGlzdCB8fCBbXSkgewogICAgICAgICAgICAgICAgdm9kX2xpc3QucHVzaCh7CiAgICAgICAgICAgICAgICAgICAgdGl0bGU6IGl0ZW0ubmFtZSwKICAgICAgICAgICAgICAgICAgICB1cmw6IGAke3RoaXMuaG9zdH0vQVBJX1JPUC9hbGJ1bS9yZXMvbGlzdD9hbGJ1bUNvZGU9JHtpdGVtLmNvZGV9YCwKICAgICAgICAgICAgICAgICAgICBkZXNjOiAoaXRlbS5wdWJsaXNoVGltZSB8fCAnJyksCiAgICAgICAgICAgICAgICAgICAgcGljX3VybDogdGhpcy5fZm9ybWF0X2ltZyhpdGVtLmltZ3NlYykKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBzZXRSZXN1bHQodm9kX2xpc3QpOwogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTsKICAgICAgICAgICAgcmV0dXJuIHNldFJlc3VsdChbXSk7CiAgICAgICAgfQogICAgfSwKICAgIAogICAgbGF6eTogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGxldCByZXNDb2RlID0gdGhpcy5pbnB1dDsKICAgICAgICBsZXQgdXJsID0gYCR7dGhpcy5ob3N0fS9BUElfUk9QL3BsYXkvZ2V0L3BsYXl1cmxgOwogICAgICAgIGxldCBwYXlsb2FkID0gewogICAgICAgICAgICAicmVzQ29kZSI6IHJlc0NvZGUsCiAgICAgICAgICAgICJpdGVtIjogInk5IiwKICAgICAgICAgICAgIm1hc2siOiAwLAogICAgICAgICAgICAibm9kZUNvZGUiOiAiMDAxMDAwIiwKICAgICAgICAgICAgInByb2plY3QiOiAibHloeGN4IiwKICAgICAgICAgICAgInB4IjogMiwKICAgICAgICAgICAgInVzZXJJZCI6ICI5MjMxNWVjNmU1OGE0NWJhN2Y0N2ZkMTQzYjNkNzk1NiIKICAgICAgICB9OwogICAgICAgIAogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGxldCByZXNwID0gYXdhaXQgdGhpcy5yZXF1ZXN0KHVybCwgeyBkYXRhOiBwYXlsb2FkIH0pOwogICAgICAgICAgICBsZXQganNvbiA9IEpTT04ucGFyc2UocmVzcCk7CiAgICAgICAgICAgIGxldCBwbGF5X3VybCA9IGpzb24ucGxheXJlcz8ucGxheXVybCB8fCAnJzsKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIHBhcnNlOiAwLAogICAgICAgICAgICAgICAgdXJsOiBwbGF5X3VybCwKICAgICAgICAgICAgICAgIGhlYWRlcjogeyAnVXNlci1BZ2VudCc6IHRoaXMuaGVhZGVyc1snVXNlci1BZ2VudCddIH0KICAgICAgICAgICAgfTsKICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICBwYXJzZTogMCwKICAgICAgICAgICAgICAgIHVybDogJycKICAgICAgICAgICAgfTsKICAgICAgICB9CiAgICB9Cn07 \ No newline at end of file diff --git "a/spider/js/\347\203\255\346\222\255\345\275\261\350\247\206.js" "b/spider/js/\347\203\255\346\222\255\345\275\261\350\247\206.js" new file mode 100644 index 00000000..4ffd935a --- /dev/null +++ "b/spider/js/\347\203\255\346\222\255\345\275\261\350\247\206.js" @@ -0,0 +1,13 @@ +/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 1, + title: '热播APP', + author: 'EylinSir', + '类型': '影视', + lang: 'ds' +}) +*/ + +dmFyIHJ1bGUgPSB7CiAgICDnsbvlnos6ICflvbHop4YnLAogICAgYXV0aG9yOiAnRXlsaW5TaXInLAogICAgdGl0bGU6ICfng63mkq1BUFAnLAogICAgZGVzYzogJ+eDreaSrUFQUOW9seinhua6kCcsCiAgICBob3N0OiAnaHR0cDovL3YucmJvdHYuY24nLAogICAgaG9tZVVybDogJ2h0dHA6Ly92LnJib3R2LmNuJywKICAgIHVybDogJy92My9ob21lL3R5cGVfc2VhcmNoJywKICAgIHNlYXJjaFVybDogJy92My9ob21lL3NlYXJjaCcsCiAgICBzZWFyY2hhYmxlOiAxLAogICAgcXVpY2tTZWFyY2g6IDEsCiAgICBmaWx0ZXJhYmxlOiAxLAogICAgdGltZW91dDogMTAwMDAsCiAgICBwbGF5X3BhcnNlOiB0cnVlLAogICAgaGVhZGVyczogewogICAgICAgICdVc2VyLUFnZW50JzogJ29raHR0cC1va2dvL2plYXNvbmx6eScsCiAgICAgICAgJ0FjY2VwdC1MYW5ndWFnZSc6ICd6aC1DTix6aDtxPTAuOCcKICAgIH0sCiAgICAKICAgIGdldGZpbGVzOiBmdW5jdGlvbiAocCA9IHt9KSB7CiAgICAgICAgbGV0IHQgPSBNYXRoLmZsb29yKERhdGUubm93KCkgLyAxMDAwKS50b1N0cmluZygpOwogICAgICAgIGxldCBzID0gbWQ1KCc3Z3AwYm5kMnNyODV5ZGlpMmozMnBjeXBzY29jNHc2YzdnNXNwbCcgKyB0KTsKICAgICAgICBsZXQgZmlsZXMgPSB7CiAgICAgICAgICAgICdzaWduJzogcywKICAgICAgICAgICAgJ3RpbWVzdGFtcCc6IHQKICAgICAgICB9OwogICAgICAgIHJldHVybiB7IC4uLnAsIC4uLmZpbGVzIH07CiAgICB9LAoKICAgIGdldHY6IGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgICAgcmV0dXJuIGRhdGEuZmlsdGVyKGkgPT4gaS52b2RfaWQgJiYgaS52b2RfaWQudG9TdHJpbmcoKSAhPT0gJzAnKS5tYXAoaSA9PiAoewogICAgICAgICAgICB0aXRsZTogaS52b2RfbmFtZSwKICAgICAgICAgICAgdXJsOiBgJHt0aGlzLmhvc3R9L3YzL2hvbWUvdm9kX2RldGFpbHM/dm9kX2lkPSR7aS52b2RfaWR9YCwKICAgICAgICAgICAgZGVzYzogaS52b2RfcmVtYXJrcywKICAgICAgICAgICAgcGljX3VybDogaS52b2RfcGljIHx8IGkudm9kX3BpY190aHVtYiwKICAgICAgICAgICAgdm9kX3llYXI6IGkudGFnCiAgICAgICAgfSkpOwogICAgfSwKICAgIAogICAg6aKE5aSE55CGOiBhc3luYyBmdW5jdGlvbiAoKSB7fSwKCiAgICBjbGFzc19wYXJzZTogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGxldCBkYXRhID0gdGhpcy5nZXRmaWxlcyh7ICcnOiAnJyB9KTsKICAgICAgICBsZXQgcmVzcCA9IGF3YWl0IF9mZXRjaChgJHt0aGlzLmhvc3R9L3YzL3R5cGUvdG9wX3R5cGVgLCB7CiAgICAgICAgICAgIG1ldGhvZDogJ3Bvc3QnLAogICAgICAgICAgICBoZWFkZXJzOiB7IC4uLnRoaXMuaGVhZGVycywgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnIH0sCiAgICAgICAgICAgIGJvZHk6IG5ldyBVUkxTZWFyY2hQYXJhbXMoZGF0YSkudG9TdHJpbmcoKQogICAgICAgIH0pOwogICAgICAgIGxldCBqc29uID0gSlNPTi5wYXJzZShhd2FpdCByZXNwLnRleHQoKSk7CiAgICAgICAgbGV0IGNsYXNzZXMgPSBqc29uLmRhdGEubGlzdC5tYXAoayA9PiAoewogICAgICAgICAgICB0eXBlX2lkOiBrLnR5cGVfaWQudG9TdHJpbmcoKSwKICAgICAgICAgICAgdHlwZV9uYW1lOiBrLnR5cGVfbmFtZQogICAgICAgIH0pKTsKICAgICAgICBsZXQgZmlsdGVycyA9IHt9OwogICAgICAgIGZvciAoY29uc3QgayBvZiBqc29uLmRhdGEubGlzdCkgewogICAgICAgICAgICBsZXQgZnRzID0gW107CiAgICAgICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGspKSB7CiAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID4gMikgewogICAgICAgICAgICAgICAgICAgIGZ0cy5wdXNoKHsKICAgICAgICAgICAgICAgICAgICAgICAgbmFtZToga2V5LAogICAgICAgICAgICAgICAgICAgICAgICBrZXksCiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZS5maWx0ZXIoaiA9PiBqICYmIGogIT09ICflhajpg6gnKS5tYXAoaiA9PiAoeyBuOiBqLCB2OiBqIH0pKQogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChmdHMubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICBmaWx0ZXJzW2sudHlwZV9pZF0gPSBmdHM7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsgY2xhc3M6IGNsYXNzZXMsIGZpbHRlcnMgfTsKICAgIH0sCiAgICAKICAgIOaOqOiNkDogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGxldCBkYXRhID0gdGhpcy5nZXRmaWxlcyh7ICcnOiAnJyB9KTsKICAgICAgICBsZXQgcmVzcCA9IGF3YWl0IF9mZXRjaChgJHt0aGlzLmhvc3R9L3YzL3R5cGUvdGpfdm9kYCwgewogICAgICAgICAgICBtZXRob2Q6ICdwb3N0JywKICAgICAgICAgICAgaGVhZGVyczogeyAuLi50aGlzLmhlYWRlcnMsICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyB9LAogICAgICAgICAgICBib2R5OiBuZXcgVVJMU2VhcmNoUGFyYW1zKGRhdGEpLnRvU3RyaW5nKCkKICAgICAgICB9KTsKICAgICAgICBsZXQganNvbiA9IEpTT04ucGFyc2UoYXdhaXQgcmVzcC50ZXh0KCkpOwogICAgICAgIGxldCB2aWRlb3MgPSB0aGlzLmdldHYoanNvbi5kYXRhLmNhaS5jb25jYXQoanNvbi5kYXRhLmxvb3ApKTsKICAgICAgICByZXR1cm4gc2V0UmVzdWx0KHZpZGVvcyk7CiAgICB9LAogICAgCiAgICDkuIDnuqc6IGFzeW5jIGZ1bmN0aW9uICh0aWQsIHBnLCBmaWx0ZXIsIGV4dGVuZCkgewogICAgICAgIGxldCBmaWxlcyA9IHsKICAgICAgICAgICAgJ3R5cGVfaWQnOiB0aWQsCiAgICAgICAgICAgICdsaW1pdCc6ICcxMicsCiAgICAgICAgICAgICdwYWdlJzogcGcKICAgICAgICB9OwogICAgICAgIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKGV4dGVuZCB8fCB7fSkpIHsKICAgICAgICAgICAgbGV0IGtleSA9IGsgPT09ICdleHRlbmQnID8gJ2NsYXNzJyA6IGs7CiAgICAgICAgICAgIGZpbGVzW2tleV0gPSB2OwogICAgICAgIH0KICAgICAgICBsZXQgZGF0YSA9IHRoaXMuZ2V0ZmlsZXMoZmlsZXMpOwogICAgICAgIGxldCByZXNwID0gYXdhaXQgX2ZldGNoKGAke3RoaXMuaG9zdH0vdjMvaG9tZS90eXBlX3NlYXJjaGAsIHsKICAgICAgICAgICAgbWV0aG9kOiAncG9zdCcsCiAgICAgICAgICAgIGhlYWRlcnM6IHsgLi4udGhpcy5oZWFkZXJzLCAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcgfSwKICAgICAgICAgICAgYm9keTogbmV3IFVSTFNlYXJjaFBhcmFtcyhkYXRhKS50b1N0cmluZygpCiAgICAgICAgfSk7CiAgICAgICAgbGV0IGpzb24gPSBKU09OLnBhcnNlKGF3YWl0IHJlc3AudGV4dCgpKTsKICAgICAgICBsZXQgdmlkZW9zID0gdGhpcy5nZXR2KGpzb24uZGF0YS5saXN0KTsKICAgICAgICByZXR1cm4gc2V0UmVzdWx0KHZpZGVvcyk7CiAgICB9LAogICAgCiAgICDkuoznuqc6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgdm9kSWQgPSB0aGlzLmlucHV0Lm1hdGNoKC92b2RfaWQ9KFxkKykvKVsxXTsKICAgICAgICBsZXQgZGF0YSA9IHRoaXMuZ2V0ZmlsZXMoeyAndm9kX2lkJzogdm9kSWQgfSk7CiAgICAgICAgbGV0IHJlc3AgPSBhd2FpdCBfZmV0Y2goYCR7dGhpcy5ob3N0fS92My9ob21lL3ZvZF9kZXRhaWxzYCwgewogICAgICAgICAgICBtZXRob2Q6ICdwb3N0JywKICAgICAgICAgICAgaGVhZGVyczogeyAuLi50aGlzLmhlYWRlcnMsICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyB9LAogICAgICAgICAgICBib2R5OiBuZXcgVVJMU2VhcmNoUGFyYW1zKGRhdGEpLnRvU3RyaW5nKCkKICAgICAgICB9KTsKICAgICAgICBsZXQgdiA9IEpTT04ucGFyc2UoYXdhaXQgcmVzcC50ZXh0KCkpLmRhdGE7CiAgICAgICAgbGV0IFZPRCA9IHsKICAgICAgICAgICAgdm9kX2lkOiB2LnZvZF9pZC50b1N0cmluZygpLAogICAgICAgICAgICB2b2RfbmFtZTogdi52b2RfbmFtZSwKICAgICAgICAgICAgdHlwZV9uYW1lOiB2LnR5cGVfbmFtZSwKICAgICAgICAgICAgdm9kX3llYXI6IHYudm9kX3llYXIsCiAgICAgICAgICAgIHZvZF9hcmVhOiB2LnZvZF9hcmVhLAogICAgICAgICAgICB2b2RfcmVtYXJrczogdi52b2RfcmVtYXJrcywKICAgICAgICAgICAgdm9kX2FjdG9yOiB2LnZvZF9hY3RvciwKICAgICAgICAgICAgdm9kX2RpcmVjdG9yOiB2LnZvZF9kaXJlY3RvciwKICAgICAgICAgICAgdm9kX2NvbnRlbnQ6ICh2LnZvZF9jb250ZW50IHx8ICfml6AnKS5yZXBsYWNlKC88W14+XSo+L2csICcnKS50cmltKCkKICAgICAgICB9OwogICAgICAgIGxldCBuID0gW107CiAgICAgICAgbGV0IHAgPSBbXTsKICAgICAgICBmb3IgKGNvbnN0IGkgb2Ygdi52b2RfcGxheV9saXN0KSB7CiAgICAgICAgICAgIGxldCBwYXJzZXMgPSBpLnBhcnNlX3VybHMuam9pbignLCcpOwogICAgICAgICAgICBsZXQgdXJscyA9IGkudXJscy5tYXAoaiA9PiBgJHtqLm5hbWV9JCR7ai51cmx9QCR7cGFyc2VzfUAke2kudWEgfHwgJyd9QCR7aS5yZWZlcmVyIHx8ICcnfWApOwogICAgICAgICAgICBwLnB1c2godXJscy5qb2luKCcjJykpOwogICAgICAgICAgICBsZXQgbmFtZSA9IChpLnRpdGxlIHx8IGkubmFtZSB8fCAnJykucmVwbGFjZSgvW1wo77yIXSg/OueCueWHu3zmjaIpW14pXSpbXCnvvIldfFta4pa24p2k44CQXS4qL2csICcnKTsKICAgICAgICAgICAgbi5wdXNoKG5hbWUgPT09IGkuZmxhZyA/IG5hbWUgOiBgJHtuYW1lfSgke2kuZmxhZ30pYCk7CiAgICAgICAgfQogICAgICAgIFZPRC52b2RfcGxheV9mcm9tID0gbi5qb2luKCckJCQnKTsKICAgICAgICBWT0Qudm9kX3BsYXlfdXJsID0gcC5qb2luKCckJCQnKTsKICAgICAgICByZXR1cm4gVk9EOwogICAgfSwKICAgIAogICAg5pCc57SiOiBhc3luYyBmdW5jdGlvbiAoKSB7CiAgICAgICAgbGV0IGZpbGVzID0gewogICAgICAgICAgICAnbGltaXQnOiAnMTInLAogICAgICAgICAgICAncGFnZSc6IHRoaXMuTVlfUEFHRSwKICAgICAgICAgICAgJ2tleXdvcmQnOiB0aGlzLktFWQogICAgICAgIH07CiAgICAgICAgbGV0IGRhdGEgPSB0aGlzLmdldGZpbGVzKGZpbGVzKTsKICAgICAgICBsZXQgcmVzcCA9IGF3YWl0IF9mZXRjaChgJHt0aGlzLmhvc3R9L3YzL2hvbWUvc2VhcmNoYCwgewogICAgICAgICAgICBtZXRob2Q6ICdwb3N0JywKICAgICAgICAgICAgaGVhZGVyczogeyAuLi50aGlzLmhlYWRlcnMsICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyB9LAogICAgICAgICAgICBib2R5OiBuZXcgVVJMU2VhcmNoUGFyYW1zKGRhdGEpLnRvU3RyaW5nKCkKICAgICAgICB9KTsKICAgICAgICBsZXQganNvbiA9IEpTT04ucGFyc2UoYXdhaXQgcmVzcC50ZXh0KCkpOwogICAgICAgIGxldCB2aWRlb3MgPSB0aGlzLmdldHYoanNvbi5kYXRhLmxpc3QpOwogICAgICAgIHJldHVybiBzZXRSZXN1bHQodmlkZW9zKTsKICAgIH0sCiAgICAKICAgIGxhenk6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgW3Jhd191cmwsIHBhcnNlc1N0ciA9ICcnLCB1YSA9ICcnLCByZWZlcmVyID0gJyddID0gdGhpcy5pbnB1dC5zcGxpdCgnQCcpOwogICAgICAgIGxldCBwYXJzZXMgPSBwYXJzZXNTdHIgPyBwYXJzZXNTdHIuc3BsaXQoJywnKSA6IFtdOwogICAgICAgIGxldCBwbGF5X2hlYWRlcnMgPSB7fTsKICAgICAgICBpZiAodWEpIHBsYXlfaGVhZGVyc1snVXNlci1BZ2VudCddID0gdWE7CiAgICAgICAgaWYgKHJlZmVyZXIpIHBsYXlfaGVhZGVyc1snUmVmZXJlciddID0gcmVmZXJlcjsKICAgICAgICBsZXQgZmluYWxfdXJsID0gJyc7CiAgICAgICAgbGV0IGp4ID0gMDsKICAgICAgICBmb3IgKGNvbnN0IHBhcnNlIG9mIHBhcnNlcykgewogICAgICAgICAgICBpZiAocGFyc2Uuc3RhcnRzV2l0aCgnaHR0cCcpKSB7CiAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgIGxldCByZXMgPSBhd2FpdCBfZmV0Y2gocGFyc2UgKyByYXdfdXJsLCB7IGhlYWRlcnM6IHRoaXMuaGVhZGVycyB9KTsKICAgICAgICAgICAgICAgICAgICBsZXQganNvbiA9IEpTT04ucGFyc2UoYXdhaXQgcmVzLnRleHQoKSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGpzb24udXJsICYmIGpzb24udXJsLnN0YXJ0c1dpdGgoJ2h0dHAnKSkgewogICAgICAgICAgICAgICAgICAgICAgICBmaW5hbF91cmwgPSBqc29uLnVybDsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge30KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKCFmaW5hbF91cmwgJiYgcmF3X3VybC5zdGFydHNXaXRoKCdodHRwJykpIHsKICAgICAgICAgICAgZmluYWxfdXJsID0gcmF3X3VybDsKICAgICAgICAgICAgaWYgKC8oPzp3d3dcLmlxaXlpfHZcLnFxfHZcLnlvdWt1fHd3d1wubWd0dnx3d3dcLmJpbGliaWxpKVwuY29tLy50ZXN0KHJhd191cmwpKSB7CiAgICAgICAgICAgICAgICBqeCA9IDE7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgcGFyc2U6IGp4LAogICAgICAgICAgICB1cmw6IGZpbmFsX3VybCwKICAgICAgICAgICAgaGVhZGVyOiBwbGF5X2hlYWRlcnMKICAgICAgICB9OwogICAgfQp9Ow== \ No newline at end of file diff --git "a/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" "b/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" index 7a5a2929..bcb373ef 100644 --- "a/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" +++ "b/spider/js/\347\225\252\350\214\204\345\260\217\350\257\264[\344\271\246].js" @@ -6,6 +6,7 @@ title: '番茄小说[书]', author: '道长', '类型': '小说', + logo: 'https://www.18zf.net/d/file/p/2023/1107/3ty5orktxrc.jpg', lang: 'ds' }) */ diff --git "a/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" "b/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" index d55334d0..9411cfbc 100644 --- "a/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" +++ "b/spider/js/\347\225\252\350\214\204\347\225\205\345\220\254[\345\220\254].js" @@ -5,9 +5,10 @@ quickSearch: 0, title: '番茄畅听', author: 'EylinSir', + logo: 'https://www.18zf.net/d/file/p/2023/1107/3ty5orktxrc.jpg', '类型': '听书', lang: 'ds' }) */ -dmFyIHJ1bGUgPSB7CiAgICDnsbvlnos6ICflkKzkuaYnLAogICAgYXV0aG9yOiAnRXlsaW5TaXInLAogICAgdGl0bGU6ICfnlarojITnlYXlkKwnLAogICAgaG9zdDogJ2h0dHBzOi8vcWtmcWFwaS52djl2LmNuJywKICAgIHVybDogJy9hcGkvZGlzY292ZXI/dGFiPeWQrOS5piZ0eXBlPWZ5Y2xhc3MmZ2VuZGVyPTImZ2VucmVfdHlwZT0xJnBhZ2U9e3twYWdlfX0nLAogICAgc2VhcmNoVXJsOiAnL2FwaS9zZWFyY2g/a2V5PSoqJnRhYl90eXBlPTImb2Zmc2V0PSgoZnlwYWdlLTEpKjEwKScsCiAgICBkZXRhaWxVcmw6ICcvYXBpL2RldGFpbD9ib29rX2lkPWZ5aWQnLAogICAgaGVhZGVyczogeydVc2VyLUFnZW50JzogJ1VDX1VBJ30sCiAgICBzZWFyY2hhYmxlOiAxLAogICAgcXVpY2tTZWFyY2g6IDAsCiAgICBmaWx0ZXJhYmxlOiAxLAogICAgZG91YmxlOiB0cnVlLAogICAgcGxheV9wYXJzZTogdHJ1ZSwKICAgIGxpbWl0OiAxMiwKICAgIGNsYXNzX25hbWU6ICfnsr7lk4HlsI/or7Qm55u45aOw6K+E5LmmJuS4lueVjOWOhuWPsiblkI3okZfop6Por7sm5a2m5Lmg5oiQ6ZW/JuaIj+absuiJuuacrybnlJ/mtLvnmb7np5Em5a625bqt5pWZ6IKyJuS6uuaWh+enkeWtpiblhbbku5YnLAogICAgY2xhc3NfdXJsOiAnODk5JjQ0NSYxMiYxMzImNDQ5JjExMyY5NjAmNDUwJjQ0NyYzOScsCiAgICBmaWx0ZXI6IHsKICAgICAgICAiODk5IjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6Ijg5OSJ9LHsibiI6IumDveW4giIsInYiOiIxIn0seyJuIjoi56m/6LaKIiwidiI6IjM3In0seyJuIjoi546w5Luj6KiA5oOFIiwidiI6IjMifSx7Im4iOiLlj6Tku6PoqIDmg4UiLCJ2IjoiNSJ9LHsibiI6IuaAu+ijgSIsInYiOiIyOSJ9LHsibiI6IueOhOW5uyIsInYiOiI3In0seyJuIjoi6YeN55SfIiwidiI6IjM2In0seyJuIjoi5oKs55aRIiwidiI6IjEwIn0seyJuIjoi54G15byCIiwidiI6IjEwMCJ9LHsibiI6Iuezu+e7nyIsInYiOiIxOSJ9LHsibiI6IuenjeeUsCIsInYiOiIyMyJ9LHsibiI6IueUnOWuoCIsInYiOiI5NiJ9LHsibiI6IuWuoOWmuyIsInYiOiIzMCJ9LHsibiI6IumDveW4gueUn+a0uyIsInYiOiIyIn0seyJuIjoi6LWY5am/IiwidiI6IjI1In0seyJuIjoi5YWI5ama5ZCO54ixIiwidiI6IjI2NSJ9LHsibiI6IuWuq+aWl+WuheaWlyIsInYiOiIyNDYifSx7Im4iOiLpg73luILml6XluLgiLCJ2IjoiMjYxIn0seyJuIjoi5oiY56We6LWY5am/IiwidiI6IjI3In0seyJuIjoi56We5Yy7IiwidiI6IjI2In0seyJuIjoi5b2x6KeG5bCP6K+0IiwidiI6IjQ1In0seyJuIjoi5Zu95YaF5b2x6KeGIiwidiI6Ijk5MSJ9LHsibiI6IuWbveWkluW9seinhiIsInYiOiI5OTIifSx7Im4iOiLnsr7lk4HlsI/or7QiLCJ2IjoiOTcwIn0seyJuIjoi5oKs55aR5o6o55CGIiwidiI6IjE2NSJ9LHsibiI6IuenkeW5u+Wwj+ivtCIsInYiOiIxNjYifSx7Im4iOiLmrabkvqDlsI/or7QiLCJ2IjoiOTkzIn0seyJuIjoi546E5bm75bCP6K+0IiwidiI6Ijk3MSJ9LHsibiI6IueOsOWunuWwj+ivtCIsInYiOiI0MDAifSx7Im4iOiLmg4XmhJ/lsI/or7QiLCJ2IjoiOTcyIn0seyJuIjoi5Lyg57uf546E5bm7IiwidiI6IjI1OCJ9LHsibiI6IueOi+WmgyIsInYiOiI4NSJ9LHsibiI6IuWlh+W5u+S7meS+oCIsInYiOiIyNTkifSx7Im4iOiLokIzlrp0iLCJ2IjoiMjgifSx7Im4iOiLpg73luILohJHmtJ4iLCJ2IjoiMjYyIn0seyJuIjoi6IGM5Zy6IiwidiI6IjEyNyJ9LHsibiI6IuWroeWlsyIsInYiOiI4OCJ9LHsibiI6IumDveW4guS/ruecnyIsInYiOiIxMjQifSx7Im4iOiLlubvmg7PoqIDmg4UiLCJ2IjoiMzIifSx7Im4iOiLnpZ7osaoiLCJ2IjoiMjAifSx7Im4iOiLnqbrpl7QiLCJ2IjoiNDQifSx7Im4iOiLlhbbku5YiLCJ2IjoiMzEifSx7Im4iOiLnjoTlubvoqIDmg4UiLCJ2IjoiMjQ4In0seyJuIjoi546E5bm76ISR5rSeIiwidiI6IjI1NyJ9LHsibiI6IuWOhuWPsuWPpOS7oyIsInYiOiIyNzMifSx7Im4iOiLnp5HlubvmnKvkuJYiLCJ2IjoiOCJ9LHsibiI6IuW5tOS7oyIsInYiOiI3OSJ9LHsibiI6IuWkqeaJjSIsInYiOiI5MCJ9LHsibiI6IuWls+W8uiIsInYiOiI4NiJ9LHsibiI6IuaOqOeQhiIsInYiOiI2MSJ9LHsibiI6IuiFuem7kSIsInYiOiI5MiJ9LHsibiI6IuivuOWkqeS4h+eVjCIsInYiOiI3MSJ9LHsibiI6IuWMu+acryIsInYiOiIyNDcifSx7Im4iOiLmmJ/pmYUiLCJ2IjoiNzcifSx7Im4iOiLpibTlrp0iLCJ2IjoiMTcifSx7Im4iOiLlm6LlrqAiLCJ2IjoiOTQifSx7Im4iOiLmia7njKrlkIPomY4iLCJ2IjoiOTMifSx7Im4iOiLmrabkvqAiLCJ2IjoiMTYifSx7Im4iOiLnjrDoqIDohJHmtJ4iLCJ2IjoiMjY3In0seyJuIjoi6YO95biC56eN55SwIiwidiI6IjI2MyJ9LHsibiI6IuaXoOaVjCIsInYiOiIzODQifSx7Im4iOiLnm5flopMiLCJ2IjoiODEifSx7Im4iOiLpqaznlLIiLCJ2IjoiMjY2In0seyJuIjoi55qH5ZCOIiwidiI6Ijg0In0seyJuIjoi54m556eN5YW1IiwidiI6IjM3NSJ9LHsibiI6IuWkp+WUkCIsInYiOiI3MyJ9LHsibiI6IuWFrOS4uyIsInYiOiI4MyJ9LHsibiI6IuWoseS5kOWciCIsInYiOiI0MyJ9LHsibiI6IumdkuaiheeruemprCIsInYiOiIzODcifSx7Im4iOiLlj6ToqIDohJHmtJ4iLCJ2IjoiMjUzIn0seyJuIjoi5Y6G5Y+y6ISR5rSeIiwidiI6IjI3MiJ9LHsibiI6Iuacq+S4liIsInYiOiI2OCJ9LHsibiI6IuWJkemBkyIsInYiOiI4MCJ9LHsibiI6IueOsOiogOeUnOWuoCIsInYiOiIzOTUifSx7Im4iOiLmuLjmiI/liqjmvKsiLCJ2IjoiNTcifSx7Im4iOiLmtKrojZIiLCJ2IjoiNjYifSx7Im4iOiLlv6vnqb8iLCJ2IjoiMjQifSx7Im4iOiLmmI7mnJ0iLCJ2IjoiMTI2In0seyJuIjoi5aSW5Y2WIiwidiI6Ijc1In0seyJuIjoi5qCh6IqxIiwidiI6IjM4NSJ9LHsibiI6IuWltueIuCIsInYiOiI0MiJ9LHsibiI6IuagoeWbrSIsInYiOiI0In0seyJuIjoi5LiJ5Zu9IiwidiI6IjY3In0seyJuIjoi55u05pKtIiwidiI6IjY5In0seyJuIjoi56m/5LmmIiwidiI6IjM4MiJ9LHsibiI6Iua1t+WymyIsInYiOiI0MCJ9LHsibiI6Iue+jumjnyIsInYiOiI3OCJ9LHsibiI6IuWPjea0viIsInYiOiIzNjkifSx7Im4iOiLnjrDoqIDlpI3ku4ciLCJ2IjoiMjY4In0seyJuIjoi6KW/5ri46KGN55SfIiwidiI6IjM3MyJ9LHsibiI6IuaxgueUnyIsInYiOiIzNzkifSx7Im4iOiLmsJHlm70iLCJ2IjoiMzkwIn0seyJuIjoi5a625bqtIiwidiI6IjEyNSJ9LHsibiI6IuWtpumcuCIsInYiOiI4MiJ9LHsibiI6Iueah+WPlCIsInYiOiI4NyJ9LHsibiI6IuWuoOeJqSIsInYiOiI3NCJ9LHsibiI6IuaXoENQIiwidiI6IjM5MiJ9LHsibiI6IuWls+aJrueUt+ijhSIsInYiOiIzODgifSx7Im4iOiLnvZHmuLgiLCJ2IjoiMzcyIn0seyJuIjoi55eF5aiHIiwidiI6IjM4MCJ9LHsibiI6IueyvueBtSIsInYiOiI4OSJ9LHsibiI6IuiZkOaWhyIsInYiOiI5NSJ9LHsibiI6IumDveW4gumdkuaYpSIsInYiOiIzOTYifSx7Im4iOiLmuIXnqb8iLCJ2IjoiNzYifV19XSwKICAgICAgICAiNDQ1IjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjQ0NSJ9LHsibiI6IumDreW+t+e6siIsInYiOiIxMjgifSx7Im4iOiLnlLDov57lhYMiLCJ2IjoiMjAzIn0seyJuIjoi5YiY5YWw6IqzIiwidiI6IjIwMiJ9LHsibiI6IuWwj+WTgSIsInYiOiIxMTQifSx7Im4iOiLoooHpmJTmiJAiLCJ2IjoiMjA0In0seyJuIjoi5Y2V55Sw6IqzIiwidiI6IjIwMSJ9LHsibiI6IuivhOS5piIsInYiOiIxMTAifSx7Im4iOiLnm7jlo7AiLCJ2IjoiMTExIn1dfV0sCiAgICAgICAgIjEyIjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjEyIn0seyJuIjoi6a2P5pmL5Y2X5YyX5pydIiwidiI6IjIwOSJ9LHsibiI6IuenpuaxiSIsInYiOiIyMDgifSx7Im4iOiLkuJbnlYzlj7IiLCJ2IjoiMjE0In0seyJuIjoi5ZSQ5a6LIiwidiI6IjIxMCJ9LHsibiI6IuaYjua4hSIsInYiOiIyMTEifSx7Im4iOiLov5HnjrDku6MiLCJ2IjoiMjEzIn0seyJuIjoi5Lit5Zu95Y+yIiwidiI6IjIxMiJ9LHsibiI6IuaImOS6ieWPsiIsInYiOiIyMDYifSx7Im4iOiLlkI3kurrkvKAiLCJ2IjoiMjA3In0seyJuIjoi5Lit5Zu95Y6G5Y+yIiwidiI6IjQwMiJ9LHsibiI6IuS4lueVjOWOhuWPsiIsInYiOiI0MDMifSx7Im4iOiLljoblj7LlsI/or7QiLCJ2IjoiOTg4In0seyJuIjoi5Y6G5Y+y5paH5YyWIiwidiI6IjI0MSJ9XX1dLAogICAgICAgICIxMzIiOiBbe2tleTogInR5cGUiLCBuYW1lOiAi57G75Z6LIiwgdmFsdWU6IFt7Im4iOiLlhajpg6giLCJ2IjoiMTMyIn0seyJuIjoi5oiY5LqJIiwidiI6Ijk3In0seyJuIjoi5Lit5Zu95ZCN6JGXIiwidiI6Ijk4In0seyJuIjoi5aSW5Zu95ZCN6JGXIiwidiI6Ijk5In0seyJuIjoi57uP566h5Yqx5b+XIiwidiI6IjI0MiJ9LHsibiI6IuS6uueJqeS8oOiusCIsInYiOiI0MDkifSx7Im4iOiLnu4/lhbjmloflraYiLCJ2IjoiMjQzIn0seyJuIjoi6Z2S5pil5paH5a2mIiwidiI6IjE2OCJ9LHsibiI6IuaImOS6ieWGm+aXhSIsInYiOiI5NzMifV19XSwKICAgICAgICAiNDQ5IjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjQ0OSJ9LHsibiI6IuazleW+iyIsInYiOiIxNDIifSx7Im4iOiLlv4PnkIYiLCJ2IjoiMTQ2In0seyJuIjoi5b+D55CG5a2mIiwidiI6IjQwNyJ9LHsibiI6IuWwkeWEv+W/g+eQhiIsInYiOiI5ODYifSx7Im4iOiLlv4PnkIbnlpfmhIgiLCJ2IjoiOTk0In0seyJuIjoi5oqV6LWE55CG6LSiIiwidiI6IjE0MyJ9LHsibiI6IuiBjOS4muiBjOWcuiIsInYiOiIxNDUifSx7Im4iOiLnu4/nrqHllYbkuJoiLCJ2IjoiMjM4In0seyJuIjoi5rKf6YCa6KGo6L6+IiwidiI6IjE0NCJ9LHsibiI6IuWKseW/l+aIkOWKnyIsInYiOiIyMzkifV19XSwKICAgICAgICAiMTEzIjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjExMyJ9LHsibiI6IuS6rOWJpyIsInYiOiIxNzEifSx7Im4iOiLotorliaciLCJ2IjoiMTcyIn0seyJuIjoi6buE5qKF5oiPIiwidiI6IjE3MyJ9LHsibiI6IuivhOWJpyIsInYiOiIxNzQifSx7Im4iOiLosavliaciLCJ2IjoiMTc1In0seyJuIjoi5piG5puyIiwidiI6IjE3NiJ9LHsibiI6IuiJuuacryIsInYiOiIxMzQifSx7Im4iOiLoibrmnK/mlofljJYiLCJ2IjoiOTQ1In0seyJuIjoi6Z+z5LmQ6Iie6LmIIiwidiI6Ijk0NiJ9LHsibiI6Iue7mOeUuyIsInYiOiI5NTkifSx7Im4iOiLmkYTlvbEiLCJ2IjoiOTYxIn0seyJuIjoi6Ym06LWP55CG6K66IiwidiI6Ijk2MiJ9XX1dLAogICAgICAgICI5NjAiOiBbe2tleTogInR5cGUiLCBuYW1lOiAi57G75Z6LIiwgdmFsdWU6IFt7Im4iOiLlhajpg6giLCJ2IjoiOTYwIn0seyJuIjoi576O6aOf54O56aWqIiwidiI6IjI0MCJ9LHsibiI6IuaXhea4uCIsInYiOiIxNTgifSx7Im4iOiLlgaXlurflhbvnlJ8iLCJ2IjoiMTU5In0seyJuIjoi6L+Q5Yqo5YGl6LqrIiwidiI6IjQxNyJ9LHsibiI6IuaXtuWwmue+juWmhiIsInYiOiI0MTgifSx7Im4iOiLnvo7po5/kvJHpl7IiLCJ2IjoiNDE5In0seyJuIjoi5a625bGF5peF5ri4IiwidiI6IjQyMCJ9LHsibiI6IumjjuawtOWNoOWNnCIsInYiOiI0MjEifSx7Im4iOiLnmb7np5HluLjor4YiLCJ2IjoiOTYzIn0seyJuIjoi55Sf5rS75oOF5oSfIiwidiI6Ijk2NCJ9XX1dLAogICAgICAgICI0NTAiOiBbe2tleTogInR5cGUiLCBuYW1lOiAi57G75Z6LIiwgdmFsdWU6IFt7Im4iOiLlhajpg6giLCJ2IjoiNDUwIn0seyJuIjoi5Lqy5a2QIiwidiI6IjQ0NyJ9LHsibiI6IuWpmuWnuyIsInYiOiIyMzQifSx7Im4iOiLnvo7mlociLCJ2IjoiMjMwIn0seyJuIjoi5aSc6K+dIiwidiI6IjIzMiJ9LHsibiI6IuWls+aApyIsInYiOiIyMzEifSx7Im4iOiLlv4PnkIblgaXlurciLCJ2IjoiMjMzIn0seyJuIjoi5oOF5oSf5pWF5LqLIiwidiI6IjIyOSJ9LHsibiI6IuS6p+WQjuaKpOeQhiIsInYiOiIyMjYifSx7Im4iOiLlhL/nq6Xoi7Hor60iLCJ2IjoiMjIyIn0seyJuIjoi5a2V5pyf5L+d5YGlIiwidiI6IjIyNyJ9LHsibiI6IuS6suWtkOWBpeW6tyIsInYiOiIyMjgifSx7Im4iOiLnp5Hmma4iLCJ2IjoiMjIzIn0seyJuIjoi5Zu95a2m5Y6G5Y+yIiwidiI6IjIyNCJ9LHsibiI6IuiDjuaVmeaXqeaVmSIsInYiOiIyMjUifSx7Im4iOiLlhL/nq6XmloflraYiLCJ2IjoiMjIwIn1dfV0sCiAgICAgICAgIjQ0NyI6IFt7a2V5OiAidHlwZSIsIG5hbWU6ICLnsbvlnosiLCB2YWx1ZTogW3sibiI6IuWFqOmDqCIsInYiOiI0NDcifSx7Im4iOiLnp5HlrabmioDmnK8iLCJ2IjoiMTAwMCJ9LHsibiI6IuiHqueEtuenkeWtpiIsInYiOiIxMzYifSx7Im4iOiLkvZvlraYiLCJ2IjoiMTE1In0seyJuIjoi56S+56eRIiwidiI6IjIzNyJ9LHsibiI6IuWbveWtpiIsInYiOiIxMTYifSx7Im4iOiLmlaPmlofmiI/liaciLCJ2IjoiMjM2In0seyJuIjoi5paH5YyWIiwidiI6IjExOCJ9LHsibiI6IuaKgOacryIsInYiOiI5NjkifSx7Im4iOiLnp5HlraYiLCJ2IjoiOTc5In0seyJuIjoi5bel5LiaIiwidiI6Ijk4MCJ9LHsibiI6IuWGnOael+eJp+a4lCIsInYiOiI5ODEifSx7Im4iOiLorqHnrpfmnLoiLCJ2IjoiOTgyIn0seyJuIjoi5bu6562R5Zut5p6XIiwidiI6Ijk4MyJ9XX1dLAogICAgICAgICIzOSI6IFt7a2V5OiAidHlwZSIsIG5hbWU6ICLnsbvlnosiLCB2YWx1ZTogW3sibiI6IuS6jOasoeWFgyIsInYiOiIzOSJ9LHsibiI6IuWoseS5kCIsInYiOiIxMjEifSx7Im4iOiLnuqrlvZUiLCJ2IjoiMTMzIn0seyJuIjoi5paw6Ze7IiwidiI6IjQ0NiJ9XX1dCiAgICB9LAoKICAgIOS4gOe6pzogYXN5bmMgZnVuY3Rpb24gKHRpZCwgcGcsIGZpbHRlciwgZXh0ZW5kKSB7CiAgICAgICAgbGV0IHBhZ2UgPSBwZyB8fCAxOwogICAgICAgIGxldCB0eXBlSWQgPSAoZXh0ZW5kICYmIGV4dGVuZC50eXBlKSA/IGV4dGVuZC50eXBlIDogdGlkOwogICAgICAgIGxldCBmaW5hbFVybCA9IGAke3RoaXMuaG9zdH0vYXBpL2Rpc2NvdmVyP3RhYj3lkKzkuaYmdHlwZT0ke3R5cGVJZH0mZ2VuZGVyPTImZ2VucmVfdHlwZT0xJnBhZ2U9JHtwYWdlfWA7CiAgICAgICAgbGV0IGpzb24gPSBhd2FpdCByZXF1ZXN0KGZpbmFsVXJsKTsKICAgICAgICBsZXQgZGF0YSA9IEpTT04ucGFyc2UoanNvbik7CiAgICAgICAgbGV0IGJvb2tfbGlzdCA9IGRhdGEuY29kZSA9PT0gMjAwID8gZGF0YS5kYXRhIDogW107CiAgICAgICAgbGV0IGQgPSBbXTsKICAgICAgICBib29rX2xpc3QuZm9yRWFjaCgoaXQpID0+IHsKICAgICAgICAgICAgZC5wdXNoKHsKICAgICAgICAgICAgICAgIHRpdGxlOiBpdC5ib29rX25hbWUgfHwgaXQuQm9va05hbWUsCiAgICAgICAgICAgICAgICB1cmw6IGl0LmJvb2tfaWQgfHwgaXQuQm9va0lkLAogICAgICAgICAgICAgICAgZGVzYzogaXQuYXV0aG9yIHx8IGl0LkF1dGhvciwKICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGl0LmFic3RyYWN0IHx8IGl0LkFic3RyYWN0IHx8IGl0LmJvb2tfYWJzdHJhY3RfdjIsCiAgICAgICAgICAgICAgICBwaWNfdXJsOiBpdC50aHVtYl91cmwgfHwgaXQuVGh1bWJVUkwgfHwgaXQuYXVkaW9fdGh1bWJfdXJpCiAgICAgICAgICAgIH0pOwogICAgICAgIH0pOwoKICAgICAgICByZXR1cm4gc2V0UmVzdWx0KGQpOwogICAgfSwKCiAgICDkuoznuqc6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgZGV0YWlsQXBpID0gYCR7dGhpcy5ob3N0fS9hcGkvZGV0YWlsP2Jvb2tfaWQ9JHt0aGlzLm9ySWR9YDsKICAgICAgICBsZXQgZGV0YWlsSnNvbiA9IGF3YWl0IHJlcXVlc3QoZGV0YWlsQXBpKTsKICAgICAgICBsZXQgZGV0YWlsRGF0YSA9IEpTT04ucGFyc2UoZGV0YWlsSnNvbik7CiAgICAgICAgbGV0IGRhdGEgPSBkZXRhaWxEYXRhLmRhdGEuZGF0YTsKICAgICAgICBsZXQgY2hhcHRlcnNBcGkgPSBgJHt0aGlzLmhvc3R9L2FwaS9ib29rP2Jvb2tfaWQ9JHt0aGlzLm9ySWR9YDsKICAgICAgICBsZXQgY2hhcHRlcnNKc29uID0gYXdhaXQgcmVxdWVzdChjaGFwdGVyc0FwaSk7CiAgICAgICAgbGV0IGNoYXB0ZXJzRGF0YSA9IEpTT04ucGFyc2UoY2hhcHRlcnNKc29uKTsKICAgICAgICBsZXQgYm9va0RhdGEgPSBjaGFwdGVyc0RhdGEuZGF0YS5kYXRhOwogICAgICAgIGxldCBsaXN0ID0gYm9va0RhdGEuY2hhcHRlckxpc3RXaXRoVm9sdW1lPy5mbGF0KCkgfHwgYm9va0RhdGEuY2hhcHRlckxpc3QgfHwgW107CiAgICAgICAgbGV0IHVybHMgPSBsaXN0Lm1hcChpdCA9PiBpdC50aXRsZSArICckJyArIGl0Lml0ZW1JZCArICdAJyArIGl0LnRpdGxlKS5qb2luKCcjJyk7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgdm9kX2lkOiB0aGlzLm9ySWQsCiAgICAgICAgICAgIHZvZF9uYW1lOiBkYXRhLmJvb2tfbmFtZSwKICAgICAgICAgICAgdHlwZV9uYW1lOiBkYXRhLmNhdGVnb3J5LAogICAgICAgICAgICB2b2RfcGljOiBkYXRhLnRodW1iX3VybCB8fCBkYXRhLmV4cGFuZF90aHVtYl91cmwsCiAgICAgICAgICAgIHZvZF9jb250ZW50OiBkYXRhLmFic3RyYWN0IHx8IGRhdGEuYm9va19hYnN0cmFjdF92MiwKICAgICAgICAgICAgdm9kX3JlbWFya3M6IGRhdGEuc3ViX2luZm8sCiAgICAgICAgICAgIHZvZF9kaXJlY3RvcjogZGF0YS5hdXRob3IsCiAgICAgICAgICAgIHZvZF9wbGF5X2Zyb206ICfnlarojITnlYXlkKwnLAogICAgICAgICAgICB2b2RfcGxheV91cmw6IHVybHMKICAgICAgICB9OwogICAgfSwKCiAgICDmkJzntKI6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQge2lucHV0fSA9IHRoaXM7CiAgICAgICAgbGV0IGh0bWwgPSBhd2FpdCByZXF1ZXN0KGlucHV0KTsKICAgICAgICBsZXQganNvbiA9IEpTT04ucGFyc2UoaHRtbCk7CiAgICAgICAgbGV0IGRhdGEgPSBqc29uLmRhdGEuc2VhcmNoX3RhYnNbNF0uZGF0YTsKICAgICAgICBsZXQgZCA9IFtdOwogICAgICAgIGZvciAobGV0IGl0IG9mIGRhdGEuZmlsdGVyKGkgPT4gaS5ib29rX2RhdGEpKSB7CiAgICAgICAgICAgIGxldCBib29rID0gaXQuYm9va19kYXRhWzBdOwogICAgICAgICAgICBkLnB1c2goewogICAgICAgICAgICAgICAgdGl0bGU6IGJvb2suYm9va19uYW1lLAogICAgICAgICAgICAgICAgdXJsOiBib29rLmJvb2tfaWQsCiAgICAgICAgICAgICAgICBkZXNjOiBib29rLmF1dGhvciwKICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGJvb2suYm9va19hYnN0cmFjdCB8fCBib29rLmFic3RyYWN0LAogICAgICAgICAgICAgICAgcGljX3VybDogYm9vay50aHVtYl91cmwKICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZXRSZXN1bHQoZCk7CiAgICB9LAoKICAgIGxhenk6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQge2lucHV0fSA9IHRoaXM7CiAgICAgICAgbGV0IHBhcnRzID0gaW5wdXQuc3BsaXQoJ0AnKTsKICAgICAgICBsZXQgaXRlbUlkID0gcGFydHNbMF07CiAgICAgICAgbGV0IHRvbmVJZCA9ICcxJzsKICAgICAgICBsZXQgY29udGVudF91cmwgPSBgJHt0aGlzLmhvc3R9L2FwaS9jb250ZW50P2l0ZW1faWQ9JHtpdGVtSWR9JnRhYj3lkKzkuaYmdG9uZV9pZD0ke3RvbmVJZH1gOwogICAgICAgIGxldCBqc29uU3RyID0gYXdhaXQgcmVxdWVzdChjb250ZW50X3VybCk7CiAgICAgICAgbGV0IGRhdGEgPSBKU09OLnBhcnNlKGpzb25TdHIpOwogICAgICAgIHJldHVybiB7cGFyc2U6IDAsIHVybDogZGF0YS5kYXRhLmNvbnRlbnR9OwogICAgfQp9Ow== \ No newline at end of file +dmFyIHJ1bGUgPSB7CiAgICDnsbvlnos6ICflkKzkuaYnLAogICAgYXV0aG9yOiAnRXlsaW5TaXInLAogICAgdGl0bGU6ICfnlarojITnlYXlkKwnLAogICAgaG9zdDogJ2h0dHBzOi8vcWtmcWFwaS52djl2LmNuJywKICAgIHVybDogJy9hcGkvZGlzY292ZXI/dGFiPeWQrOS5piZ0eXBlPWZ5Y2xhc3MmZ2VuZGVyPTImZ2VucmVfdHlwZT0xJnBhZ2U9e3twYWdlfX0nLAogICAgc2VhcmNoVXJsOiAnL2FwaS9zZWFyY2g/a2V5PSoqJnRhYl90eXBlPTImb2Zmc2V0PSgoZnlwYWdlLTEpKjEwKScsCiAgICBkZXRhaWxVcmw6ICcvYXBpL2RldGFpbD9ib29rX2lkPWZ5aWQnLAogICAgaGVhZGVyczogeydVc2VyLUFnZW50JzogJ1VDX1VBJ30sCiAgICBzZWFyY2hhYmxlOiAxLAogICAgcXVpY2tTZWFyY2g6IDAsCiAgICBmaWx0ZXJhYmxlOiAxLAogICAgZG91YmxlOiB0cnVlLAogICAgcGxheV9wYXJzZTogdHJ1ZSwKICAgIGxpbWl0OiAxMiwKICAgIGNsYXNzX25hbWU6ICfnsr7lk4HlsI/or7Qm55u45aOw6K+E5LmmJuS4lueVjOWOhuWPsiblkI3okZfop6Por7sm5a2m5Lmg5oiQ6ZW/JuaIj+absuiJuuacrybnlJ/mtLvnmb7np5Em5a625bqt5pWZ6IKyJuS6uuaWh+enkeWtpiblhbbku5YnLAogICAgY2xhc3NfdXJsOiAnODk5JjQ0NSYxMiYxMzImNDQ5JjExMyY5NjAmNDUwJjQ0NyYzOScsCiAgICBmaWx0ZXI6IHsKICAgICAgICAiODk5IjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6Ijg5OSJ9LHsibiI6IumDveW4giIsInYiOiIxIn0seyJuIjoi56m/6LaKIiwidiI6IjM3In0seyJuIjoi546w5Luj6KiA5oOFIiwidiI6IjMifSx7Im4iOiLlj6Tku6PoqIDmg4UiLCJ2IjoiNSJ9LHsibiI6IuaAu+ijgSIsInYiOiIyOSJ9LHsibiI6IueOhOW5uyIsInYiOiI3In0seyJuIjoi6YeN55SfIiwidiI6IjM2In0seyJuIjoi5oKs55aRIiwidiI6IjEwIn0seyJuIjoi54G15byCIiwidiI6IjEwMCJ9LHsibiI6Iuezu+e7nyIsInYiOiIxOSJ9LHsibiI6IuenjeeUsCIsInYiOiIyMyJ9LHsibiI6IueUnOWuoCIsInYiOiI5NiJ9LHsibiI6IuWuoOWmuyIsInYiOiIzMCJ9LHsibiI6IumDveW4gueUn+a0uyIsInYiOiIyIn0seyJuIjoi6LWY5am/IiwidiI6IjI1In0seyJuIjoi5YWI5ama5ZCO54ixIiwidiI6IjI2NSJ9LHsibiI6IuWuq+aWl+WuheaWlyIsInYiOiIyNDYifSx7Im4iOiLpg73luILml6XluLgiLCJ2IjoiMjYxIn0seyJuIjoi5oiY56We6LWY5am/IiwidiI6IjI3In0seyJuIjoi56We5Yy7IiwidiI6IjI2In0seyJuIjoi5b2x6KeG5bCP6K+0IiwidiI6IjQ1In0seyJuIjoi5Zu95YaF5b2x6KeGIiwidiI6Ijk5MSJ9LHsibiI6IuWbveWkluW9seinhiIsInYiOiI5OTIifSx7Im4iOiLnsr7lk4HlsI/or7QiLCJ2IjoiOTcwIn0seyJuIjoi5oKs55aR5o6o55CGIiwidiI6IjE2NSJ9LHsibiI6IuenkeW5u+Wwj+ivtCIsInYiOiIxNjYifSx7Im4iOiLmrabkvqDlsI/or7QiLCJ2IjoiOTkzIn0seyJuIjoi546E5bm75bCP6K+0IiwidiI6Ijk3MSJ9LHsibiI6IueOsOWunuWwj+ivtCIsInYiOiI0MDAifSx7Im4iOiLmg4XmhJ/lsI/or7QiLCJ2IjoiOTcyIn0seyJuIjoi5Lyg57uf546E5bm7IiwidiI6IjI1OCJ9LHsibiI6IueOi+WmgyIsInYiOiI4NSJ9LHsibiI6IuWlh+W5u+S7meS+oCIsInYiOiIyNTkifSx7Im4iOiLokIzlrp0iLCJ2IjoiMjgifSx7Im4iOiLpg73luILohJHmtJ4iLCJ2IjoiMjYyIn0seyJuIjoi6IGM5Zy6IiwidiI6IjEyNyJ9LHsibiI6IuWroeWlsyIsInYiOiI4OCJ9LHsibiI6IumDveW4guS/ruecnyIsInYiOiIxMjQifSx7Im4iOiLlubvmg7PoqIDmg4UiLCJ2IjoiMzIifSx7Im4iOiLnpZ7osaoiLCJ2IjoiMjAifSx7Im4iOiLnqbrpl7QiLCJ2IjoiNDQifSx7Im4iOiLlhbbku5YiLCJ2IjoiMzEifSx7Im4iOiLnjoTlubvoqIDmg4UiLCJ2IjoiMjQ4In0seyJuIjoi546E5bm76ISR5rSeIiwidiI6IjI1NyJ9LHsibiI6IuWOhuWPsuWPpOS7oyIsInYiOiIyNzMifSx7Im4iOiLnp5HlubvmnKvkuJYiLCJ2IjoiOCJ9LHsibiI6IuW5tOS7oyIsInYiOiI3OSJ9LHsibiI6IuWkqeaJjSIsInYiOiI5MCJ9LHsibiI6IuWls+W8uiIsInYiOiI4NiJ9LHsibiI6IuaOqOeQhiIsInYiOiI2MSJ9LHsibiI6IuiFuem7kSIsInYiOiI5MiJ9LHsibiI6IuivuOWkqeS4h+eVjCIsInYiOiI3MSJ9LHsibiI6IuWMu+acryIsInYiOiIyNDcifSx7Im4iOiLmmJ/pmYUiLCJ2IjoiNzcifSx7Im4iOiLpibTlrp0iLCJ2IjoiMTcifSx7Im4iOiLlm6LlrqAiLCJ2IjoiOTQifSx7Im4iOiLmia7njKrlkIPomY4iLCJ2IjoiOTMifSx7Im4iOiLmrabkvqAiLCJ2IjoiMTYifSx7Im4iOiLnjrDoqIDohJHmtJ4iLCJ2IjoiMjY3In0seyJuIjoi6YO95biC56eN55SwIiwidiI6IjI2MyJ9LHsibiI6IuaXoOaVjCIsInYiOiIzODQifSx7Im4iOiLnm5flopMiLCJ2IjoiODEifSx7Im4iOiLpqaznlLIiLCJ2IjoiMjY2In0seyJuIjoi55qH5ZCOIiwidiI6Ijg0In0seyJuIjoi54m556eN5YW1IiwidiI6IjM3NSJ9LHsibiI6IuWkp+WUkCIsInYiOiI3MyJ9LHsibiI6IuWFrOS4uyIsInYiOiI4MyJ9LHsibiI6IuWoseS5kOWciCIsInYiOiI0MyJ9LHsibiI6IumdkuaiheeruemprCIsInYiOiIzODcifSx7Im4iOiLlj6ToqIDohJHmtJ4iLCJ2IjoiMjUzIn0seyJuIjoi5Y6G5Y+y6ISR5rSeIiwidiI6IjI3MiJ9LHsibiI6Iuacq+S4liIsInYiOiI2OCJ9LHsibiI6IuWJkemBkyIsInYiOiI4MCJ9LHsibiI6IueOsOiogOeUnOWuoCIsInYiOiIzOTUifSx7Im4iOiLmuLjmiI/liqjmvKsiLCJ2IjoiNTcifSx7Im4iOiLmtKrojZIiLCJ2IjoiNjYifSx7Im4iOiLlv6vnqb8iLCJ2IjoiMjQifSx7Im4iOiLmmI7mnJ0iLCJ2IjoiMTI2In0seyJuIjoi5aSW5Y2WIiwidiI6Ijc1In0seyJuIjoi5qCh6IqxIiwidiI6IjM4NSJ9LHsibiI6IuWltueIuCIsInYiOiI0MiJ9LHsibiI6IuagoeWbrSIsInYiOiI0In0seyJuIjoi5LiJ5Zu9IiwidiI6IjY3In0seyJuIjoi55u05pKtIiwidiI6IjY5In0seyJuIjoi56m/5LmmIiwidiI6IjM4MiJ9LHsibiI6Iua1t+WymyIsInYiOiI0MCJ9LHsibiI6Iue+jumjnyIsInYiOiI3OCJ9LHsibiI6IuWPjea0viIsInYiOiIzNjkifSx7Im4iOiLnjrDoqIDlpI3ku4ciLCJ2IjoiMjY4In0seyJuIjoi6KW/5ri46KGN55SfIiwidiI6IjM3MyJ9LHsibiI6IuaxgueUnyIsInYiOiIzNzkifSx7Im4iOiLmsJHlm70iLCJ2IjoiMzkwIn0seyJuIjoi5a625bqtIiwidiI6IjEyNSJ9LHsibiI6IuWtpumcuCIsInYiOiI4MiJ9LHsibiI6Iueah+WPlCIsInYiOiI4NyJ9LHsibiI6IuWuoOeJqSIsInYiOiI3NCJ9LHsibiI6IuaXoENQIiwidiI6IjM5MiJ9LHsibiI6IuWls+aJrueUt+ijhSIsInYiOiIzODgifSx7Im4iOiLnvZHmuLgiLCJ2IjoiMzcyIn0seyJuIjoi55eF5aiHIiwidiI6IjM4MCJ9LHsibiI6IueyvueBtSIsInYiOiI4OSJ9LHsibiI6IuiZkOaWhyIsInYiOiI5NSJ9LHsibiI6IumDveW4gumdkuaYpSIsInYiOiIzOTYifSx7Im4iOiLmuIXnqb8iLCJ2IjoiNzYifV19XSwKICAgICAgICAiNDQ1IjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjQ0NSJ9LHsibiI6IumDreW+t+e6siIsInYiOiIxMjgifSx7Im4iOiLnlLDov57lhYMiLCJ2IjoiMjAzIn0seyJuIjoi5YiY5YWw6IqzIiwidiI6IjIwMiJ9LHsibiI6IuWwj+WTgSIsInYiOiIxMTQifSx7Im4iOiLoooHpmJTmiJAiLCJ2IjoiMjA0In0seyJuIjoi5Y2V55Sw6IqzIiwidiI6IjIwMSJ9LHsibiI6IuivhOS5piIsInYiOiIxMTAifSx7Im4iOiLnm7jlo7AiLCJ2IjoiMTExIn1dfV0sCiAgICAgICAgIjEyIjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjEyIn0seyJuIjoi6a2P5pmL5Y2X5YyX5pydIiwidiI6IjIwOSJ9LHsibiI6IuenpuaxiSIsInYiOiIyMDgifSx7Im4iOiLkuJbnlYzlj7IiLCJ2IjoiMjE0In0seyJuIjoi5ZSQ5a6LIiwidiI6IjIxMCJ9LHsibiI6IuaYjua4hSIsInYiOiIyMTEifSx7Im4iOiLov5HnjrDku6MiLCJ2IjoiMjEzIn0seyJuIjoi5Lit5Zu95Y+yIiwidiI6IjIxMiJ9LHsibiI6IuaImOS6ieWPsiIsInYiOiIyMDYifSx7Im4iOiLlkI3kurrkvKAiLCJ2IjoiMjA3In0seyJuIjoi5Lit5Zu95Y6G5Y+yIiwidiI6IjQwMiJ9LHsibiI6IuS4lueVjOWOhuWPsiIsInYiOiI0MDMifSx7Im4iOiLljoblj7LlsI/or7QiLCJ2IjoiOTg4In0seyJuIjoi5Y6G5Y+y5paH5YyWIiwidiI6IjI0MSJ9XX1dLAogICAgICAgICIxMzIiOiBbe2tleTogInR5cGUiLCBuYW1lOiAi57G75Z6LIiwgdmFsdWU6IFt7Im4iOiLlhajpg6giLCJ2IjoiMTMyIn0seyJuIjoi5oiY5LqJIiwidiI6Ijk3In0seyJuIjoi5Lit5Zu95ZCN6JGXIiwidiI6Ijk4In0seyJuIjoi5aSW5Zu95ZCN6JGXIiwidiI6Ijk5In0seyJuIjoi57uP566h5Yqx5b+XIiwidiI6IjI0MiJ9LHsibiI6IuS6uueJqeS8oOiusCIsInYiOiI0MDkifSx7Im4iOiLnu4/lhbjmloflraYiLCJ2IjoiMjQzIn0seyJuIjoi6Z2S5pil5paH5a2mIiwidiI6IjE2OCJ9LHsibiI6IuaImOS6ieWGm+aXhSIsInYiOiI5NzMifV19XSwKICAgICAgICAiNDQ5IjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjQ0OSJ9LHsibiI6IuazleW+iyIsInYiOiIxNDIifSx7Im4iOiLlv4PnkIYiLCJ2IjoiMTQ2In0seyJuIjoi5b+D55CG5a2mIiwidiI6IjQwNyJ9LHsibiI6IuWwkeWEv+W/g+eQhiIsInYiOiI5ODYifSx7Im4iOiLlv4PnkIbnlpfmhIgiLCJ2IjoiOTk0In0seyJuIjoi5oqV6LWE55CG6LSiIiwidiI6IjE0MyJ9LHsibiI6IuiBjOS4muiBjOWcuiIsInYiOiIxNDUifSx7Im4iOiLnu4/nrqHllYbkuJoiLCJ2IjoiMjM4In0seyJuIjoi5rKf6YCa6KGo6L6+IiwidiI6IjE0NCJ9LHsibiI6IuWKseW/l+aIkOWKnyIsInYiOiIyMzkifV19XSwKICAgICAgICAiMTEzIjogW3trZXk6ICJ0eXBlIiwgbmFtZTogIuexu+WeiyIsIHZhbHVlOiBbeyJuIjoi5YWo6YOoIiwidiI6IjExMyJ9LHsibiI6IuS6rOWJpyIsInYiOiIxNzEifSx7Im4iOiLotorliaciLCJ2IjoiMTcyIn0seyJuIjoi6buE5qKF5oiPIiwidiI6IjE3MyJ9LHsibiI6IuivhOWJpyIsInYiOiIxNzQifSx7Im4iOiLosavliaciLCJ2IjoiMTc1In0seyJuIjoi5piG5puyIiwidiI6IjE3NiJ9LHsibiI6IuiJuuacryIsInYiOiIxMzQifSx7Im4iOiLoibrmnK/mlofljJYiLCJ2IjoiOTQ1In0seyJuIjoi6Z+z5LmQ6Iie6LmIIiwidiI6Ijk0NiJ9LHsibiI6Iue7mOeUuyIsInYiOiI5NTkifSx7Im4iOiLmkYTlvbEiLCJ2IjoiOTYxIn0seyJuIjoi6Ym06LWP55CG6K66IiwidiI6Ijk2MiJ9XX1dLAogICAgICAgICI5NjAiOiBbe2tleTogInR5cGUiLCBuYW1lOiAi57G75Z6LIiwgdmFsdWU6IFt7Im4iOiLlhajpg6giLCJ2IjoiOTYwIn0seyJuIjoi576O6aOf54O56aWqIiwidiI6IjI0MCJ9LHsibiI6IuaXhea4uCIsInYiOiIxNTgifSx7Im4iOiLlgaXlurflhbvnlJ8iLCJ2IjoiMTU5In0seyJuIjoi6L+Q5Yqo5YGl6LqrIiwidiI6IjQxNyJ9LHsibiI6IuaXtuWwmue+juWmhiIsInYiOiI0MTgifSx7Im4iOiLnvo7po5/kvJHpl7IiLCJ2IjoiNDE5In0seyJuIjoi5a625bGF5peF5ri4IiwidiI6IjQyMCJ9LHsibiI6IumjjuawtOWNoOWNnCIsInYiOiI0MjEifSx7Im4iOiLnmb7np5HluLjor4YiLCJ2IjoiOTYzIn0seyJuIjoi55Sf5rS75oOF5oSfIiwidiI6Ijk2NCJ9XX1dLAogICAgICAgICI0NTAiOiBbe2tleTogInR5cGUiLCBuYW1lOiAi57G75Z6LIiwgdmFsdWU6IFt7Im4iOiLlhajpg6giLCJ2IjoiNDUwIn0seyJuIjoi5Lqy5a2QIiwidiI6IjQ0NyJ9LHsibiI6IuWpmuWnuyIsInYiOiIyMzQifSx7Im4iOiLnvo7mlociLCJ2IjoiMjMwIn0seyJuIjoi5aSc6K+dIiwidiI6IjIzMiJ9LHsibiI6IuWls+aApyIsInYiOiIyMzEifSx7Im4iOiLlv4PnkIblgaXlurciLCJ2IjoiMjMzIn0seyJuIjoi5oOF5oSf5pWF5LqLIiwidiI6IjIyOSJ9LHsibiI6IuS6p+WQjuaKpOeQhiIsInYiOiIyMjYifSx7Im4iOiLlhL/nq6Xoi7Hor60iLCJ2IjoiMjIyIn0seyJuIjoi5a2V5pyf5L+d5YGlIiwidiI6IjIyNyJ9LHsibiI6IuS6suWtkOWBpeW6tyIsInYiOiIyMjgifSx7Im4iOiLnp5Hmma4iLCJ2IjoiMjIzIn0seyJuIjoi5Zu95a2m5Y6G5Y+yIiwidiI6IjIyNCJ9LHsibiI6IuiDjuaVmeaXqeaVmSIsInYiOiIyMjUifSx7Im4iOiLlhL/nq6XmloflraYiLCJ2IjoiMjIwIn1dfV0sCiAgICAgICAgIjQ0NyI6IFt7a2V5OiAidHlwZSIsIG5hbWU6ICLnsbvlnosiLCB2YWx1ZTogW3sibiI6IuWFqOmDqCIsInYiOiI0NDcifSx7Im4iOiLnp5HlrabmioDmnK8iLCJ2IjoiMTAwMCJ9LHsibiI6IuiHqueEtuenkeWtpiIsInYiOiIxMzYifSx7Im4iOiLkvZvlraYiLCJ2IjoiMTE1In0seyJuIjoi56S+56eRIiwidiI6IjIzNyJ9LHsibiI6IuWbveWtpiIsInYiOiIxMTYifSx7Im4iOiLmlaPmlofmiI/liaciLCJ2IjoiMjM2In0seyJuIjoi5paH5YyWIiwidiI6IjExOCJ9LHsibiI6IuaKgOacryIsInYiOiI5NjkifSx7Im4iOiLnp5HlraYiLCJ2IjoiOTc5In0seyJuIjoi5bel5LiaIiwidiI6Ijk4MCJ9LHsibiI6IuWGnOael+eJp+a4lCIsInYiOiI5ODEifSx7Im4iOiLorqHnrpfmnLoiLCJ2IjoiOTgyIn0seyJuIjoi5bu6562R5Zut5p6XIiwidiI6Ijk4MyJ9XX1dLAogICAgICAgICIzOSI6IFt7a2V5OiAidHlwZSIsIG5hbWU6ICLnsbvlnosiLCB2YWx1ZTogW3sibiI6IuS6jOasoeWFgyIsInYiOiIzOSJ9LHsibiI6IuWoseS5kCIsInYiOiIxMjEifSx7Im4iOiLnuqrlvZUiLCJ2IjoiMTMzIn0seyJuIjoi5paw6Ze7IiwidiI6IjQ0NiJ9XX1dCiAgICB9LAoKICAgIOS4gOe6pzogYXN5bmMgZnVuY3Rpb24gKHRpZCwgcGcsIGZpbHRlciwgZXh0ZW5kKSB7CiAgICAgICAgbGV0IHBhZ2UgPSBwZyB8fCAxOwogICAgICAgIGxldCB0eXBlSWQgPSAoZXh0ZW5kICYmIGV4dGVuZC50eXBlKSA/IGV4dGVuZC50eXBlIDogdGlkOwogICAgICAgIGxldCBmaW5hbFVybCA9IGAke3RoaXMuaG9zdH0vYXBpL2Rpc2NvdmVyP3RhYj3lkKzkuaYmdHlwZT0ke3R5cGVJZH0mZ2VuZGVyPTImZ2VucmVfdHlwZT0xJnBhZ2U9JHtwYWdlfWA7CiAgICAgICAgbGV0IGpzb24gPSBhd2FpdCByZXF1ZXN0KGZpbmFsVXJsKTsKICAgICAgICBsZXQgZGF0YSA9IEpTT04ucGFyc2UoanNvbik7CiAgICAgICAgbGV0IGJvb2tfbGlzdCA9IGRhdGEuY29kZSA9PT0gMjAwID8gZGF0YS5kYXRhIDogW107CiAgICAgICAgbGV0IGQgPSBbXTsKICAgICAgICBib29rX2xpc3QuZm9yRWFjaCgoaXQpID0+IHsKICAgICAgICAgICAgZC5wdXNoKHsKICAgICAgICAgICAgICAgIHRpdGxlOiBpdC5ib29rX25hbWUgfHwgaXQuQm9va05hbWUsCiAgICAgICAgICAgICAgICB1cmw6IGl0LmJvb2tfaWQgfHwgaXQuQm9va0lkLAogICAgICAgICAgICAgICAgZGVzYzogaXQuYXV0aG9yIHx8IGl0LkF1dGhvciwKICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGl0LmFic3RyYWN0IHx8IGl0LkFic3RyYWN0IHx8IGl0LmJvb2tfYWJzdHJhY3RfdjIsCiAgICAgICAgICAgICAgICBwaWNfdXJsOiBpdC50aHVtYl91cmwgfHwgaXQuVGh1bWJVUkwgfHwgaXQuYXVkaW9fdGh1bWJfdXJpCiAgICAgICAgICAgIH0pOwogICAgICAgIH0pOwoKICAgICAgICByZXR1cm4gc2V0UmVzdWx0KGQpOwogICAgfSwKCiAgICDkuoznuqc6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgZGV0YWlsQXBpID0gYCR7dGhpcy5ob3N0fS9hcGkvZGV0YWlsP2Jvb2tfaWQ9JHt0aGlzLm9ySWR9YDsKICAgICAgICBsZXQgZGV0YWlsSnNvbiA9IGF3YWl0IHJlcXVlc3QoZGV0YWlsQXBpKTsKICAgICAgICBsZXQgZGV0YWlsRGF0YSA9IEpTT04ucGFyc2UoZGV0YWlsSnNvbik7CiAgICAgICAgbGV0IGRhdGEgPSBkZXRhaWxEYXRhLmRhdGEuZGF0YTsKICAgICAgICBsZXQgY2hhcHRlcnNBcGkgPSBgJHt0aGlzLmhvc3R9L2FwaS9ib29rP2Jvb2tfaWQ9JHt0aGlzLm9ySWR9YDsKICAgICAgICBsZXQgY2hhcHRlcnNKc29uID0gYXdhaXQgcmVxdWVzdChjaGFwdGVyc0FwaSk7CiAgICAgICAgbGV0IGNoYXB0ZXJzRGF0YSA9IEpTT04ucGFyc2UoY2hhcHRlcnNKc29uKTsKICAgICAgICBsZXQgYm9va0RhdGEgPSBjaGFwdGVyc0RhdGEuZGF0YS5kYXRhOwogICAgICAgIGxldCBsaXN0ID0gYm9va0RhdGEuY2hhcHRlckxpc3RXaXRoVm9sdW1lPy5mbGF0KCkgfHwgYm9va0RhdGEuY2hhcHRlckxpc3QgfHwgW107CiAgICAgICAgbGV0IHVybHMgPSBsaXN0Lm1hcChpdCA9PiBpdC50aXRsZSArICckJyArIGl0Lml0ZW1JZCArICdAJyArIGl0LnRpdGxlKS5qb2luKCcjJyk7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgdm9kX2lkOiB0aGlzLm9ySWQsCiAgICAgICAgICAgIHZvZF9uYW1lOiBkYXRhLmJvb2tfbmFtZSwKICAgICAgICAgICAgdHlwZV9uYW1lOiBkYXRhLmNhdGVnb3J5LAogICAgICAgICAgICB2b2RfcGljOiBkYXRhLnRodW1iX3VybCB8fCBkYXRhLmV4cGFuZF90aHVtYl91cmwsCiAgICAgICAgICAgIHZvZF9jb250ZW50OiBkYXRhLmFic3RyYWN0IHx8IGRhdGEuYm9va19hYnN0cmFjdF92MiwKICAgICAgICAgICAgdm9kX3JlbWFya3M6IGRhdGEuc3ViX2luZm8sCiAgICAgICAgICAgIHZvZF9kaXJlY3RvcjogZGF0YS5hdXRob3IsCiAgICAgICAgICAgIHZvZF9wbGF5X2Zyb206ICfnlarojITnlYXlkKwnLAogICAgICAgICAgICB2b2RfcGxheV91cmw6IHVybHMKICAgICAgICB9OwogICAgfSwKCiAgICDmkJzntKI6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQge2lucHV0fSA9IHRoaXM7CiAgICAgICAgbGV0IGh0bWwgPSBhd2FpdCByZXF1ZXN0KGlucHV0KTsKICAgICAgICBsZXQganNvbiA9IEpTT04ucGFyc2UoaHRtbCk7CiAgICAgICAgbGV0IGRhdGEgPSBqc29uLmRhdGEuc2VhcmNoX3RhYnNbNF0uZGF0YTsKICAgICAgICBsZXQgZCA9IFtdOwogICAgICAgIGZvciAobGV0IGl0IG9mIGRhdGEuZmlsdGVyKGkgPT4gaS5ib29rX2RhdGEpKSB7CiAgICAgICAgICAgIGxldCBib29rID0gaXQuYm9va19kYXRhWzBdOwogICAgICAgICAgICBkLnB1c2goewogICAgICAgICAgICAgICAgdGl0bGU6IGJvb2suYm9va19uYW1lLAogICAgICAgICAgICAgICAgdXJsOiBib29rLmJvb2tfaWQsCiAgICAgICAgICAgICAgICBkZXNjOiBib29rLmF1dGhvciwKICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGJvb2suYm9va19hYnN0cmFjdCB8fCBib29rLmFic3RyYWN0LAogICAgICAgICAgICAgICAgcGljX3VybDogYm9vay50aHVtYl91cmwKICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZXRSZXN1bHQoZCk7CiAgICB9LAoKICAgIGxhenk6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQge2lucHV0fSA9IHRoaXM7CiAgICAgICAgbGV0IHBhcnRzID0gaW5wdXQuc3BsaXQoJ0AnKTsKICAgICAgICBsZXQgaXRlbUlkID0gcGFydHNbMF07CiAgICAgICAgbGV0IHRvbmVJZCA9ICcxJzsKICAgICAgICBsZXQgY29udGVudF91cmwgPSBgJHt0aGlzLmhvc3R9L2FwaS9jb250ZW50P2l0ZW1faWQ9JHtpdGVtSWR9JnRhYj3lkKzkuaYmdG9uZV9pZD0ke3RvbmVJZH1gOwogICAgICAgIGxldCBqc29uU3RyID0gYXdhaXQgcmVxdWVzdChjb250ZW50X3VybCk7CiAgICAgICAgbGV0IGRhdGEgPSBKU09OLnBhcnNlKGpzb25TdHIpOwogICAgICAgIHJldHVybiB7cGFyc2U6IDAsIHVybDogZGF0YS5kYXRhLmNvbnRlbnR9OwogICAgfQp9Ow== diff --git "a/spider/js/\347\225\252\350\214\204\347\237\255\345\211\247[\347\237\255].js" "b/spider/js/\347\225\252\350\214\204\347\237\255\345\211\247[\347\237\255].js" index ac10661c..001dd9a4 100644 --- "a/spider/js/\347\225\252\350\214\204\347\237\255\345\211\247[\347\237\255].js" +++ "b/spider/js/\347\225\252\350\214\204\347\237\255\345\211\247[\347\237\255].js" @@ -4,6 +4,7 @@ filterable: 0, quickSearch: 0, title: '番茄短剧', + logo: 'https://www.18zf.net/d/file/p/2023/1107/3ty5orktxrc.jpg', '类型': '影视', lang: 'ds' }) @@ -177,4 +178,4 @@ var rule = { }); return VODS }, -} \ No newline at end of file +} diff --git "a/spider/js/\350\277\275\346\226\260\345\244\247\345\205\250.js" "b/spider/js/\350\277\275\346\226\260\345\244\247\345\205\250.js" new file mode 100644 index 00000000..e7a48126 --- /dev/null +++ "b/spider/js/\350\277\275\346\226\260\345\244\247\345\205\250.js" @@ -0,0 +1,13 @@ +/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 0, + title: '追新大全', + author: 'EylinSir', + '类型': '影视', + lang: 'ds' +}) +*/ + +dmFyIHJ1bGUgPSB7CiAgICDnsbvlnos6ICflvbHop4YnLAogICAgYXV0aG9yOiAnRXlsaW5TaXInLAogICAgdGl0bGU6ICfov73mlrDlpKflhagnLAogICAgaG9zdDogJ2h0dHA6Ly96eHlzLmdhb3pob3Vrai5jbicsCiAgICBob21lVXJsOiAnaHR0cDovL3p4eXMuZ2FvemhvdWtqLmNuJywKICAgIHVybDogJy9wdWJsaWMvP3NlcnZpY2U9QXBwLk1vdi5HZXRPbmxpbmVMaXN0JnR5cGVfaWQ9ZnljbGFzcyZwYWdlPWZ5cGFnZSZsaW1pdD0xOCcsCiAgICBzZWFyY2hVcmw6ICcvcHVibGljLz9zZXJ2aWNlPUFwcC5Nb3YuU2VhcmNoVm9kJmtleT0qKicsCiAgICBzZWFyY2hhYmxlOiAxLAogICAgcXVpY2tTZWFyY2g6IDAsCiAgICBmaWx0ZXJhYmxlOiAxLAogICAgdGltZW91dDogMTAwMDAsCiAgICBwbGF5X3BhcnNlOiB0cnVlLAogICAga2V5OiAnJywKICAgIGl2OiAnMTIzNDU2Nzg5MDEyMzQ1NicsCiAgICBoZWFkZXJzOiB7CiAgICAgICAgJ1VzZXItQWdlbnQnOiAnb2todHRwLzMuMTIuMCcsCiAgICAgICAgJ0Nvbm5lY3Rpb24nOiAnS2VlcC1BbGl2ZScsCiAgICAgICAgJ0FjY2VwdC1FbmNvZGluZyc6ICdnemlwJwogICAgfSwKICAgIAogICAgY2xhc3NfcGFyc2U6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBpZiAoIXRoaXMuaG9zdCkgcmV0dXJuIHsgY2xhc3M6IFtdLCBmaWx0ZXJzOiB7fSB9OwogICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIGNsYXNzOiBbCiAgICAgICAgICAgICAgICB7ICd0eXBlX2lkJzogJzEnLCAndHlwZV9uYW1lJzogJ+eUteW9sScgfSwKICAgICAgICAgICAgICAgIHsgJ3R5cGVfaWQnOiAnMicsICd0eXBlX25hbWUnOiAn6L+e57ut5YmnJyB9LAogICAgICAgICAgICAgICAgeyAndHlwZV9pZCc6ICczJywgJ3R5cGVfbmFtZSc6ICfnu7zoibonIH0sCiAgICAgICAgICAgICAgICB7ICd0eXBlX2lkJzogJzQnLCAndHlwZV9uYW1lJzogJ+WKqOa8qycgfQogICAgICAgICAgICBdLAogICAgICAgICAgICBmaWx0ZXJzOiB7fQogICAgICAgIH07CiAgICB9LAoKICAgIOmihOWkhOeQhjogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGxldCByZXNwMSA9IGF3YWl0IF9mZXRjaChgJHt0aGlzLmhvc3R9L3B1YmxpYy8/c2VydmljZT1BcHAuTW92LkdldFR5cGVMaXN0YCwgeyBoZWFkZXJzOiB0aGlzLmhlYWRlcnMgfSk7CiAgICAgICAgICAgIGxldCB0ZXh0MSA9IGF3YWl0IHJlc3AxLnRleHQoKTsKICAgICAgICAgICAgaWYgKHRleHQxLnN0YXJ0c1dpdGgoJ++7vycpKSB0ZXh0MSA9IHRleHQxLnN1YnN0cmluZygxKTsKICAgICAgICAgICAgbGV0IGRhdGExID0gSlNPTi5wYXJzZSh0ZXh0MSk7CiAgICAgICAgICAgIGxldCBzaWduX3N0YXJ0ID0gKGRhdGExLkRhdGEgfHwgW10pLmZpbmQoaSA9PiBpLnR5cGVfaWQudG9TdHJpbmcoKSA9PT0gJzEnKT8udHlwZV91bmlvbiB8fCAnJzsKICAgICAgICAgICAgbGV0IHJlc3AyID0gYXdhaXQgX2ZldGNoKGAke3RoaXMuaG9zdH0vcHVibGljLz9zZXJ2aWNlPUFwcC5Nb3YuR2V0QWRUeXBlYCwgeyBoZWFkZXJzOiB0aGlzLmhlYWRlcnMgfSk7CiAgICAgICAgICAgIGxldCB0ZXh0MiA9IGF3YWl0IHJlc3AyLnRleHQoKTsKICAgICAgICAgICAgaWYgKHRleHQyLnN0YXJ0c1dpdGgoJ++7vycpKSB0ZXh0MiA9IHRleHQyLnN1YnN0cmluZygxKTsKICAgICAgICAgICAgbGV0IGRhdGEyID0gSlNPTi5wYXJzZSh0ZXh0Mik7CiAgICAgICAgICAgIGxldCBzaWduX2VuZCA9IGRhdGEyLkRhdGEudG1wIHx8ICcnOwogICAgICAgICAgICBsZXQgZnVsbEtleSA9IHNpZ25fc3RhcnQgKyBzaWduX2VuZDsKICAgICAgICAgICAgaWYgKGZ1bGxLZXkubGVuZ3RoID49IDE2KSB7CiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGZ1bGxLZXkuc3Vic3RyaW5nKDAsIDE2KTsKICAgICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgY29uc29sZS5lcnJvcign5Yid5aeL5YyWIEtleSDlpLHotKU6JywgZSk7CiAgICAgICAgICAgIHRoaXMuaG9zdCA9ICcnOwogICAgICAgIH0KICAgIH0sCiAgICAKICAgIOaOqOiNkDogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGlmICghdGhpcy5ob3N0KSByZXR1cm4gc2V0UmVzdWx0KFtdKTsKICAgICAgICBsZXQgcmVzcCA9IGF3YWl0IF9mZXRjaChgJHt0aGlzLmhvc3R9L3B1YmxpYy8/c2VydmljZT1BcHAuTW92LkdldEhvbWVMZXZlbGAsIHsgaGVhZGVyczogdGhpcy5oZWFkZXJzIH0pOwogICAgICAgIGxldCB0ZXh0ID0gYXdhaXQgcmVzcC50ZXh0KCk7CiAgICAgICAgaWYgKHRleHQuc3RhcnRzV2l0aCgn77u/JykpIHRleHQgPSB0ZXh0LnN1YnN0cmluZygxKTsKICAgICAgICBsZXQgZGF0YSA9IEpTT04ucGFyc2UodGV4dCk7CiAgICAgICAgCiAgICAgICAgbGV0IHZpZGVvcyA9IHR5cGVvZiBkYXRhID09PSAnb2JqZWN0JyAmJiBkYXRhICE9PSBudWxsID8gCiAgICAgICAgICAgIE9iamVjdC52YWx1ZXMoZGF0YSkKICAgICAgICAgICAgICAgIC5maWx0ZXIoaXRlbSA9PiB0eXBlb2YgaXRlbSA9PT0gJ29iamVjdCcgJiYgaXRlbSAhPT0gbnVsbCkKICAgICAgICAgICAgICAgIC5mbGF0TWFwKGl0ZW0gPT4gT2JqZWN0LnZhbHVlcyhpdGVtKSkKICAgICAgICAgICAgICAgIC5maWx0ZXIoQXJyYXkuaXNBcnJheSkKICAgICAgICAgICAgICAgIC5mbGF0TWFwKGxpc3QgPT4gbGlzdC5tYXAoayA9PiAoewogICAgICAgICAgICAgICAgICAgIHRpdGxlOiBrLnZvZF9uYW1lLAogICAgICAgICAgICAgICAgICAgIHVybDogYCR7dGhpcy5ob3N0fS9wdWJsaWMvP3NlcnZpY2U9QXBwLk1vdi5HZXRPbmxpbmVNdkJ5SWQmdm9kaWQ9JHtrLnZvZF9pZH1gLAogICAgICAgICAgICAgICAgICAgIGRlc2M6IGsudm9kX3JlbWFya3MsCiAgICAgICAgICAgICAgICAgICAgcGljX3VybDogay52b2RfcGljLAogICAgICAgICAgICAgICAgICAgIHZvZF95ZWFyOiBrLnZvZF95ZWFyLAogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGsudm9kX2NvbnRlbnQKICAgICAgICAgICAgICAgIH0pKSkKICAgICAgICAgICAgOiBbXTsKICAgICAgICAKICAgICAgICByZXR1cm4gc2V0UmVzdWx0KHZpZGVvcyk7CiAgICB9LAogICAgCiAgICDkuIDnuqc6IGFzeW5jIGZ1bmN0aW9uICh0aWQsIHBnLCBmaWx0ZXIsIGV4dGVuZCkgewogICAgICAgIGlmICghdGhpcy5ob3N0KSByZXR1cm4gc2V0UmVzdWx0KFtdKTsKICAgICAgICBsZXQgdXJsID0gYCR7dGhpcy5ob3N0fS9wdWJsaWMvP3NlcnZpY2U9QXBwLk1vdi5HZXRPbmxpbmVMaXN0JnR5cGVfaWQ9JHt0aWR9JnBhZ2U9JHtwZ30mbGltaXQ9MThgOwogICAgICAgIGxldCByZXNwID0gYXdhaXQgX2ZldGNoKHVybCwgeyBoZWFkZXJzOiB0aGlzLmhlYWRlcnMgfSk7CiAgICAgICAgbGV0IHRleHQgPSBhd2FpdCByZXNwLnRleHQoKTsKICAgICAgICBpZiAodGV4dC5zdGFydHNXaXRoKCfvu78nKSkgdGV4dCA9IHRleHQuc3Vic3RyaW5nKDEpOwogICAgICAgIGxldCBkYXRhID0gSlNPTi5wYXJzZSh0ZXh0KTsKICAgICAgICBsZXQgdmlkZW9zID0gKGRhdGEuRGF0YSB8fCBbXSkubWFwKGkgPT4gKHsKICAgICAgICAgICAgdGl0bGU6IGkudm9kX25hbWUsCiAgICAgICAgICAgIHVybDogYCR7dGhpcy5ob3N0fS9wdWJsaWMvP3NlcnZpY2U9QXBwLk1vdi5HZXRPbmxpbmVNdkJ5SWQmdm9kaWQ9JHtpLnZvZF9pZH1gLAogICAgICAgICAgICBkZXNjOiBpLnZvZF9yZW1hcmtzLAogICAgICAgICAgICBwaWNfdXJsOiBpLnZvZF9waWMsCiAgICAgICAgICAgIHZvZF95ZWFyOiBpLnZvZF95ZWFyLAogICAgICAgICAgICBjb250ZW50OiBpLnZvZF9jb250ZW50CiAgICAgICAgfSkpOwogICAgICAgIHJldHVybiBzZXRSZXN1bHQodmlkZW9zKTsKICAgIH0sCiAgICAKICAgIOS6jOe6pzogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGxldCB2b2RJZCA9IHRoaXMuaW5wdXQubWF0Y2goL3ZvZGlkPShcZCspLylbMV07CiAgICAgICAgbGV0IHVybCA9IGAke3RoaXMuaG9zdH0vcHVibGljLz9zZXJ2aWNlPUFwcC5Nb3YuR2V0T25saW5lTXZCeUlkJnZvZGlkPSR7dm9kSWR9YDsKICAgICAgICBsZXQgcmVzcCA9IGF3YWl0IF9mZXRjaCh1cmwsIHsgaGVhZGVyczogdGhpcy5oZWFkZXJzIH0pOwogICAgICAgIGxldCB0ZXh0ID0gYXdhaXQgcmVzcC50ZXh0KCk7CiAgICAgICAgaWYgKHRleHQuc3RhcnRzV2l0aCgn77u/JykpIHRleHQgPSB0ZXh0LnN1YnN0cmluZygxKTsKICAgICAgICBsZXQgZGF0YSA9IEpTT04ucGFyc2UodGV4dCk7CiAgICAgICAgbGV0IGZpcnN0SXRlbSA9IChkYXRhLkRhdGEgfHwgW10pLmZpbmQoaSA9PiB0eXBlb2YgaSA9PT0gJ29iamVjdCcgJiYgaSAhPT0gbnVsbCk7CiAgICAgICAgCiAgICAgICAgaWYgKGZpcnN0SXRlbSkgewogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgdm9kX2lkOiBmaXJzdEl0ZW0udm9kX2lkLnRvU3RyaW5nKCksCiAgICAgICAgICAgICAgICB2b2RfbmFtZTogZmlyc3RJdGVtLnZvZF9uYW1lLAogICAgICAgICAgICAgICAgdm9kX3BpYzogZmlyc3RJdGVtLnZvZF9waWMsCiAgICAgICAgICAgICAgICB2b2RfcmVtYXJrczogZmlyc3RJdGVtLnZvZF9yZW1hcmtzLAogICAgICAgICAgICAgICAgdm9kX3llYXI6IGZpcnN0SXRlbS52b2RfeWVhciwKICAgICAgICAgICAgICAgIHZvZF9hcmVhOiBmaXJzdEl0ZW0udm9kX2FyZWEsCiAgICAgICAgICAgICAgICB2b2RfYWN0b3I6IGZpcnN0SXRlbS52b2RfYWN0b3IsCiAgICAgICAgICAgICAgICB2b2RfY29udGVudDogZmlyc3RJdGVtLnZvZF9jb250ZW50LAogICAgICAgICAgICAgICAgdm9kX3BsYXlfZnJvbTogZmlyc3RJdGVtLnZvZF9wbGF5X2Zyb20sCiAgICAgICAgICAgICAgICB2b2RfcGxheV91cmw6IGZpcnN0SXRlbS52b2RfcGxheV91cmwsCiAgICAgICAgICAgICAgICB0eXBlX25hbWU6IGZpcnN0SXRlbS52b2RfY2xhc3MKICAgICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgcmV0dXJuIHt9OwogICAgfSwKICAgIAogICAg5pCc57SiOiBhc3luYyBmdW5jdGlvbiAoKSB7CiAgICAgICAgaWYgKCF0aGlzLmhvc3QpIHJldHVybiBzZXRSZXN1bHQoW10pOwogICAgICAgIGxldCB1cmwgPSBgJHt0aGlzLmhvc3R9L3B1YmxpYy8/c2VydmljZT1BcHAuTW92LlNlYXJjaFZvZCZrZXk9JHtlbmNvZGVVUklDb21wb25lbnQodGhpcy5LRVkpfWA7CiAgICAgICAgbGV0IHJlc3AgPSBhd2FpdCBfZmV0Y2godXJsLCB7IGhlYWRlcnM6IHRoaXMuaGVhZGVycyB9KTsKICAgICAgICBsZXQgdGV4dCA9IGF3YWl0IHJlc3AudGV4dCgpOwogICAgICAgIGlmICh0ZXh0LnN0YXJ0c1dpdGgoJ++7vycpKSB0ZXh0ID0gdGV4dC5zdWJzdHJpbmcoMSk7CiAgICAgICAgbGV0IGRhdGEgPSBKU09OLnBhcnNlKHRleHQpOwogICAgICAgIGxldCB2aWRlb3MgPSAoZGF0YS5EYXRhIHx8IFtdKS5tYXAoaSA9PiAoewogICAgICAgICAgICB0aXRsZTogaS52b2RfbmFtZSwKICAgICAgICAgICAgdXJsOiBgJHt0aGlzLmhvc3R9L3B1YmxpYy8/c2VydmljZT1BcHAuTW92LkdldE9ubGluZU12QnlJZCZ2b2RpZD0ke2kudm9kX2lkfWAsCiAgICAgICAgICAgIGRlc2M6IGkudm9kX3JlbWFya3MsCiAgICAgICAgICAgIHBpY191cmw6IGkudm9kX3BpYywKICAgICAgICAgICAgdm9kX3llYXI6IGkudm9kX3llYXIsCiAgICAgICAgICAgIGNvbnRlbnQ6IGkudm9kX2NvbnRlbnQKICAgICAgICB9KSk7CiAgICAgICAgcmV0dXJuIHNldFJlc3VsdCh2aWRlb3MpOwogICAgfSwKICAgIAogICAgbGF6eTogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGxldCBqeCA9IDA7CiAgICAgICAgbGV0IHVybCA9ICcnOwogICAgICAgIGxldCB1YSA9ICdjb20uZ2prai56eHlzZHEvMS4xLjAgKExpbnV4O0FuZHJvaWQgMTIpIEV4b1BsYXllckxpYi8yLjEyLjMnOwogICAgICAgIGxldCBpZCA9IHRoaXMuaW5wdXQ7CiAgICAgICAgaWYgKGlkLm1hdGNoKC9eaHR0cHM/OlwvXC8uKlwuKG0zdTh8bXA0fGZsdnxta3YpL2kpKSB7CiAgICAgICAgICAgIHVybCA9IGlkOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICBsZXQgcmVzcCA9IGF3YWl0IF9mZXRjaChgJHt0aGlzLmhvc3R9L3B1YmxpYy8/c2VydmljZT1BcHAuTW92LkdldE12SlhVcmxCeVVybCZ1cmw9JHtpZH1gLCB7IGhlYWRlcnM6IHRoaXMuaGVhZGVycyB9KTsKICAgICAgICAgICAgICAgIGxldCB0ZXh0ID0gYXdhaXQgcmVzcC50ZXh0KCk7CiAgICAgICAgICAgICAgICBpZiAodGV4dC5zdGFydHNXaXRoKCfvu78nKSkgdGV4dCA9IHRleHQuc3Vic3RyaW5nKDEpOwogICAgICAgICAgICAgICAgbGV0IGRhdGEgPSBKU09OLnBhcnNlKHRleHQpOwogICAgICAgICAgICAgICAgbGV0IHJhd191cmwgPSBkYXRhLkRhdGEudXJsOwogICAgICAgICAgICAgICAgLy8g5bCd6K+V5L2/55SoQ3J5cHRvSlPov5vooYxBRVPop6Plr4YKICAgICAgICAgICAgICAgIGlmICh0aGlzLmtleSkgewogICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBrZXkgPSBDcnlwdG9KUy5lbmMuVXRmOC5wYXJzZSh0aGlzLmtleSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBpdiA9IENyeXB0b0pTLmVuYy5VdGY4LnBhcnNlKHRoaXMuaXYpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgZGVjcnlwdGVkVXJsID0gQ3J5cHRvSlMuQUVTLmRlY3J5cHQocmF3X3VybCwga2V5LCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGU6IENyeXB0b0pTLm1vZGUuQ0JDLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFkZGluZzogQ3J5cHRvSlMucGFkLlBrY3M1CiAgICAgICAgICAgICAgICAgICAgICAgIH0pLnRvU3RyaW5nKENyeXB0b0pTLmVuYy5VdGY4KTsKICAgICAgICAgICAgICAgICAgICAgICAgdXJsID0gZGVjcnlwdGVkVXJsICYmIGRlY3J5cHRlZFVybC5zdGFydHNXaXRoKCdodHRwJykgPyBkZWNyeXB0ZWRVcmwgOiB1cmw7CiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdBRVPop6Plr4blpLHotKU6JywgZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICBpZiAoLyg/Ond3d1wuaXFpeWl8dlwucXF8dlwueW91a3V8d3d3XC5tZ3R2fHd3d1wuYmlsaWJpbGkpXC5jb20vLnRlc3QoaWQpKSB7CiAgICAgICAgICAgICAgICAgICAgdXJsID0gaWQ7CiAgICAgICAgICAgICAgICAgICAganggPSAxOwogICAgICAgICAgICAgICAgICAgIHVhID0gTU9CSUxFX1VBOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIAogICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIHBhcnNlOiBqeCwKICAgICAgICAgICAgdXJsLAogICAgICAgICAgICBoZWFkZXI6IHsgJ1VzZXItQWdlbnQnOiB1YSB9CiAgICAgICAgfTsKICAgIH0KfTs= \ No newline at end of file From db6b9840cf2d8160fa699b8820d32aac1876ab7e Mon Sep 17 00:00:00 2001 From: eylinsir <283371717@qq.com> Date: Wed, 21 Jan 2026 18:46:25 +0800 Subject: [PATCH 061/101] Update files and directories --- ...1\220\350\201\232\345\220\210[\345\220\254].js" | 14 ++++++++++++++ ...5\220\351\237\263\344\271\220[\345\220\254].js" | 0 ...5\220\351\237\263\344\271\220[\345\220\254].js" | 0 ...261\263\345\205\224\351\237\263\344\271\220.js" | 0 .../\350\234\273\350\234\223FM[\345\220\254].js" | 0 5 files changed, 14 insertions(+) create mode 100644 "spider/js/\351\237\263\344\271\220\350\201\232\345\220\210[\345\220\254].js" rename "spider/js/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" => "spider/js_bad/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" (100%) rename "spider/js_dr2/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" => "spider/js_dr2_old/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" (100%) rename "spider/js_dr2/\347\261\263\345\205\224\351\237\263\344\271\220.js" => "spider/js_dr2_old/\347\261\263\345\205\224\351\237\263\344\271\220.js" (100%) rename "spider/js_dr2/\350\234\273\350\234\223FM[\345\220\254].js" => "spider/js_dr2_old/\350\234\273\350\234\223FM[\345\220\254].js" (100%) diff --git "a/spider/js/\351\237\263\344\271\220\350\201\232\345\220\210[\345\220\254].js" "b/spider/js/\351\237\263\344\271\220\350\201\232\345\220\210[\345\220\254].js" new file mode 100644 index 00000000..94802096 --- /dev/null +++ "b/spider/js/\351\237\263\344\271\220\350\201\232\345\220\210[\345\220\254].js" @@ -0,0 +1,14 @@ +/* +@header({ + searchable: 1, + filterable: 1, + quickSearch: 1, + title: '音乐聚合', + author: 'EylinSir', + '类型': '音乐', + logo: 'https://pic.5577.com/up/2021-9/202198191801219.png', + lang: 'ds' +}) +*/ + +dmFyIHJ1bGUgPSB7CiAgICDnsbvlnos6ICfpn7PkuZAnLAogICAgYXV0aG9yOiAnRXlsaW5TaXInLAogICAgdGl0bGU6ICfpn7PkuZDogZrlkIgnLAogICAgaG9zdDogJ2h0dHBzOi8vbXVzaWMtZGwuc2F5cXouY29tJywKICAgIGxvZ286ICdodHRwczovL3BpYy41NTc3LmNvbS91cC8yMDIxLTkvMjAyMTk4MTkxODAxMjE5LnBuZycsCiAgICBoZWFkZXJzOiB7CiAgICAgICAgJ1VzZXItQWdlbnQnOiBNT0JJTEVfVUEKICAgIH0sCiAgICBzZWFyY2hhYmxlOiAxLAogICAgcXVpY2tTZWFyY2g6IDEsCiAgICBmaWx0ZXJhYmxlOiAxLAogICAgdGltZW91dDogMTAwMDAsCiAgICBwbGF5X3BhcnNlOiB0cnVlLAogICAgY2xhc3NfbmFtZTogJ+e9keaYk+S6kemfs+S5kCZRUemfs+S5kCbphbfmiJHpn7PkuZAnLAogICAgY2xhc3NfdXJsOiAnbmV0ZWFzZSZxcSZrdXdvJywKICAgIHNlYXJjaFVybDogJy9hcGkvP3R5cGU9YWdncmVnYXRlU2VhcmNoJmtleXdvcmQ9KiombGltaXQ9MTAmcGFnZT0xJywKICAgIHR5cGVzOiBbCiAgICAgICAgeyBuYW1lOiAnSGktUmVz6Z+z6LSoJywgdmFsdWU6ICdmbGFjMjRiaXQnIH0sCiAgICAgICAgeyBuYW1lOiAn5peg5o2f6Z+z6LSoJywgdmFsdWU6ICdmbGFjJyB9LAogICAgICAgIHsgbmFtZTogJ+mrmOWTgemfs+i0qCcsIHZhbHVlOiAnMzIwaycgfSwKICAgICAgICB7IG5hbWU6ICfmoIflh4bpn7PotKgnLCB2YWx1ZTogJzEyOGsnIH0KICAgIF0sCiAgICBwbGF0Zm9ybXM6IFsnbmV0ZWFzZScsICdxcScsICdrdXdvJ10sCiAgICBwbGF0Zm9ybU5hbWVNYXA6IHsKICAgICAgICBuZXRlYXNlOiAn572R5piT5LqR6Z+z5LmQJywKICAgICAgICBxcTogJ1FR6Z+z5LmQJywKICAgICAgICBrdXdvOiAn6YW35oiR6Z+z5LmQJwogICAgfSwKCiAgICDkuIDnuqc6IGFzeW5jIGZ1bmN0aW9uICh0aWQsIHBnLCBmaWx0ZXIsIGV4dGVuZCkgewogICAgICAgIGxldCByZXN1bHQgPSBbXTsKICAgICAgICBsZXQgdGFyZ2V0UGxhdGZvcm1zID0gdGlkICYmIHRoaXMucGxhdGZvcm1zLmluY2x1ZGVzKHRpZCkgPyBbdGlkXSA6IHRoaXMucGxhdGZvcm1zOwogICAgICAgIGZvciAobGV0IHBsYXRmb3JtIG9mIHRhcmdldFBsYXRmb3JtcykgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgbGV0IGRhdGEgPSBKU09OLnBhcnNlKGF3YWl0IHJlcXVlc3QoYCR7dGhpcy5ob3N0fS9hcGkvP3NvdXJjZT0ke3BsYXRmb3JtfSZ0eXBlPXRvcGxpc3RzYCwgeyBoZWFkZXJzOiB0aGlzLmhlYWRlcnMgfSkpOwogICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goLi4uKGRhdGE/LmNvZGUgPT09IDIwMCAmJiBkYXRhLmRhdGE/Lmxpc3QgPyAKICAgICAgICAgICAgICAgICAgICBkYXRhLmRhdGEubGlzdC5tYXAoaXRlbSA9PiAoewogICAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogaXRlbS5uYW1lLAogICAgICAgICAgICAgICAgICAgICAgICB1cmw6IGAke3BsYXRmb3JtfV8ke2l0ZW0uaWR9YCwKICAgICAgICAgICAgICAgICAgICAgICAgZGVzYzogaXRlbS51cGRhdGVGcmVxdWVuY3ksCiAgICAgICAgICAgICAgICAgICAgICAgIHBpY191cmw6IGl0ZW0ucGljCiAgICAgICAgICAgICAgICAgICAgfSkpIDogW10pKTsKICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycik7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHNldFJlc3VsdChyZXN1bHQpOwogICAgfSwKCiAgICDkuoznuqc6IGFzeW5jIGZ1bmN0aW9uICgpIHsKICAgICAgICBsZXQgW3BsYXRmb3JtLCByZWFsSWRdID0gdGhpcy5vcklkLnNwbGl0KCdfJyk7CiAgICAgICAgaWYgKCFwbGF0Zm9ybSB8fCAhcmVhbElkKSByZXR1cm4ge307CiAgICAgICAgbGV0IHNvbmdMaXN0ID0gW107CiAgICAgICAgbGV0IHZvZF9uYW1lID0gdGhpcy5vcklkOwogICAgICAgIGxldCB2b2RfZGVzYyA9ICcnOwogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGxldCByZXMgPSBhd2FpdCByZXF1ZXN0KGAke3RoaXMuaG9zdH0vYXBpLz9zb3VyY2U9JHtwbGF0Zm9ybX0maWQ9JHtyZWFsSWR9JnR5cGU9dG9wbGlzdGAsIHsgaGVhZGVyczogdGhpcy5oZWFkZXJzIH0pOwogICAgICAgICAgICBsZXQgc29uZ0RhdGEgPSBKU09OLnBhcnNlKHJlcyk7CiAgICAgICAgICAgIGlmIChzb25nRGF0YT8uY29kZSA9PT0gMjAwICYmIHNvbmdEYXRhLmRhdGE/Lmxpc3QpIHsKICAgICAgICAgICAgICAgIHNvbmdMaXN0ID0gc29uZ0RhdGEuZGF0YS5saXN0OwogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICBsZXQgdG9wTGlzdHNSZXMgPSBhd2FpdCByZXF1ZXN0KGAke3RoaXMuaG9zdH0vYXBpLz9zb3VyY2U9JHtwbGF0Zm9ybX0mdHlwZT10b3BsaXN0c2AsIHsgaGVhZGVyczogdGhpcy5oZWFkZXJzIH0pOwogICAgICAgICAgICAgICAgICAgIGxldCB0b3BMaXN0c0RhdGEgPSBKU09OLnBhcnNlKHRvcExpc3RzUmVzKTsKICAgICAgICAgICAgICAgICAgICBsZXQgY3VycmVudExpc3QgPSB0b3BMaXN0c0RhdGE/LmNvZGUgPT09IDIwMCAmJiB0b3BMaXN0c0RhdGEuZGF0YT8ubGlzdCA/IAogICAgICAgICAgICAgICAgICAgICAgICB0b3BMaXN0c0RhdGEuZGF0YS5saXN0LmZpbmQoaXRlbSA9PiBpdGVtLmlkID09PSByZWFsSWQpIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudExpc3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdm9kX25hbWUgPSBjdXJyZW50TGlzdC5uYW1lOwogICAgICAgICAgICAgICAgICAgICAgICB2b2RfZGVzYyA9IGN1cnJlbnRMaXN0LnVwZGF0ZUZyZXF1ZW5jeSB8fCAnJzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHJlcyA9IGF3YWl0IHJlcXVlc3QoYCR7dGhpcy5ob3N0fS9hcGkvP3NvdXJjZT0ke3BsYXRmb3JtfSZpZD0ke3JlYWxJZH0mdHlwZT1pbmZvYCwgeyBoZWFkZXJzOiB0aGlzLmhlYWRlcnMgfSk7CiAgICAgICAgICAgICAgICBzb25nRGF0YSA9IEpTT04ucGFyc2UocmVzKTsKICAgICAgICAgICAgICAgIGlmIChzb25nRGF0YT8uY29kZSAhPT0gMjAwIHx8ICFzb25nRGF0YS5kYXRhKSByZXR1cm4ge307CiAgICAgICAgICAgICAgICBzb25nTGlzdCA9IFtzb25nRGF0YS5kYXRhXTsKICAgICAgICAgICAgICAgIHZvZF9uYW1lID0gYCR7c29uZ0RhdGEuZGF0YS5uYW1lfSAtICR7c29uZ0RhdGEuZGF0YS5hcnRpc3R9YDsKICAgICAgICAgICAgICAgIHZvZF9kZXNjID0gc29uZ0RhdGEuZGF0YS5hbGJ1bSB8fCAnJzsKICAgICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKGVycikgewogICAgICAgICAgICBjb25zb2xlLmVycm9yKCfojrflj5bmlbDmja7lpLHotKU6JywgZXJyKTsKICAgICAgICAgICAgcmV0dXJuIHt9OwogICAgICAgIH0KCiAgICAgICAgaWYgKHZvZF9uYW1lID09PSB0aGlzLm9ySWQgJiYgc29uZ0xpc3QubGVuZ3RoKSB7CiAgICAgICAgICAgIHZvZF9uYW1lID0gYCR7c29uZ0xpc3RbMF0uYWxidW19IC0g5q2M5puy5YiX6KGoYDsKICAgICAgICAgICAgdm9kX2Rlc2MgPSBg5YWx5YyF5ZCrICR7c29uZ0xpc3QubGVuZ3RofSDpppbmrYzmm7JgOwogICAgICAgIH0KCiAgICAgICAgbGV0IHBsYXlfdXJsID0gc29uZ0xpc3QubWFwKHNvbmcgPT4gYCR7c29uZy5uYW1lfSAtICR7c29uZy5hcnRpc3R9JCR7cGxhdGZvcm19XyR7c29uZy5pZCB8fCByZWFsSWR9YCkuam9pbignIycpOwogICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIHZvZF9pZDogdGhpcy5vcklkLAogICAgICAgICAgICB2b2RfbmFtZSwKICAgICAgICAgICAgdm9kX3BsYXlfZnJvbTogdGhpcy5wbGF0Zm9ybU5hbWVNYXBbcGxhdGZvcm1dLAogICAgICAgICAgICB2b2RfcGxheV91cmw6IHBsYXlfdXJsLAogICAgICAgICAgICB2b2RfZGVzYwogICAgICAgIH07CiAgICB9LAoKICAgIOaQnOe0ojogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGxldCB1cmwgPSB0aGlzLnNlYXJjaFVybC5yZXBsYWNlKCcqKicsIGVuY29kZVVSSUNvbXBvbmVudCh0aGlzLktFWSkpOwogICAgICAgIHRyeSB7CiAgICAgICAgICAgIGxldCBkYXRhID0gYXdhaXQgcmVxdWVzdCh1cmwsIHsKICAgICAgICAgICAgICAgIGhlYWRlcnM6IHRoaXMuaGVhZGVycywKICAgICAgICAgICAgICAgIHRpbWVvdXQ6IDEwMDAwIAogICAgICAgICAgICB9KTsKICAgICAgICAgICAgbGV0IGpzb24gPSBKU09OLnBhcnNlKGRhdGEpOwogICAgICAgICAgICBpZiAoanNvbj8uY29kZSA9PT0gMjAwICYmIGpzb24/LmRhdGE/LnJlc3VsdHMpIHsKICAgICAgICAgICAgICAgIGxldCByZXN1bHQgPSBqc29uLmRhdGEucmVzdWx0cy5tYXAoaXRlbSA9PiAoewogICAgICAgICAgICAgICAgICAgIHRpdGxlOiBgJHtpdGVtLm5hbWV9IC0gJHtpdGVtLmFydGlzdH1gLAogICAgICAgICAgICAgICAgICAgIGRlc2M6IGAke2l0ZW0ucGxhdGZvcm0gPT09ICduZXRlYXNlJyA/ICfnvZHmmJPkupEnIDogaXRlbS5wbGF0Zm9ybSA9PT0gJ3FxJyA/ICdRUScgOiAn6YW35oiRJ33pn7PkuZAgLSAke2l0ZW0uYWxidW19YCwKICAgICAgICAgICAgICAgICAgICBwaWNfdXJsOiBpdGVtLnBpYywKICAgICAgICAgICAgICAgICAgICB1cmw6IGAke2l0ZW0ucGxhdGZvcm19XyR7aXRlbS5pZH1gCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICByZXR1cm4gc2V0UmVzdWx0KHJlc3VsdCk7CiAgICAgICAgICAgIH0KICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICBjb25zb2xlLmVycm9yKCfmkJzntKLor7fmsYLplJnor686JywgZXJyb3IpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gc2V0UmVzdWx0KFtdKTsKICAgIH0sCgogICAgbGF6eTogYXN5bmMgZnVuY3Rpb24gKCkgewogICAgICAgIGxldCBbcGxhdGZvcm0sIHJlYWxJZF0gPSB0aGlzLmlucHV0LnNwbGl0KCdfJyk7CiAgICAgICAgaWYgKCFwbGF0Zm9ybSB8fCAhcmVhbElkKSB7CiAgICAgICAgICAgIHJldHVybiB7IHBhcnNlOiAwLCBwbGF5VXJsOiAnJywgdXJsOiBbXSwgaGVhZGVyOiB0aGlzLmhlYWRlcnMsIGxyYzogJycsIGNvdmVyOiAnJywgaGVpZ2h0OiA3MjAgfTsKICAgICAgICB9CiAgICAgICAgbGV0IGx5cmljID0gJyc7CiAgICAgICAgbGV0IGluZm9EYXRhID0ge307CiAgICAgICAgbGV0IFtseXJpY1JlcywgaW5mb1Jlc10gPSBhd2FpdCBQcm9taXNlLmFsbChbCiAgICAgICAgICAgIHJlcXVlc3QoYCR7dGhpcy5ob3N0fS9hcGkvP3NvdXJjZT0ke3BsYXRmb3JtfSZpZD0ke3JlYWxJZH0mdHlwZT1scmNgLCB7IGhlYWRlcnM6IHRoaXMuaGVhZGVycyB9KS5jYXRjaCgoKSA9PiAnJyksCiAgICAgICAgICAgIHJlcXVlc3QoYCR7dGhpcy5ob3N0fS9hcGkvP3NvdXJjZT0ke3BsYXRmb3JtfSZpZD0ke3JlYWxJZH0mdHlwZT1pbmZvYCwgeyBoZWFkZXJzOiB0aGlzLmhlYWRlcnMgfSkuY2F0Y2goKCkgPT4gJ3t9JykKICAgICAgICBdKTsKICAgICAgICBpZiAodHlwZW9mIGx5cmljUmVzID09PSAnc3RyaW5nJykgbHlyaWMgPSBseXJpY1JlczsKICAgICAgICB0cnkgewogICAgICAgICAgICBpbmZvRGF0YSA9IEpTT04ucGFyc2UoaW5mb1Jlcyk7CiAgICAgICAgfSBjYXRjaCAoZXJyKSB7fQogICAgICAgIGxldCBjb3ZlciA9IGluZm9EYXRhPy5jb2RlID09PSAyMDAgPyBpbmZvRGF0YS5kYXRhPy5waWMgfHwgJycgOiAnJzsKICAgICAgICBsZXQgdXJsID0gdGhpcy50eXBlcy5mbGF0TWFwKHR5cGUgPT4gW3R5cGUubmFtZSwgYCR7dGhpcy5ob3N0fS9hcGkvP3NvdXJjZT0ke3BsYXRmb3JtfSZpZD0ke3JlYWxJZH0mdHlwZT11cmwmYnI9JHt0eXBlLnZhbHVlfWBdKTsKICAgICAgICByZXR1cm4gewogICAgICAgICAgICBwYXJzZTogMCwKICAgICAgICAgICAgcGxheVVybDogJycsCiAgICAgICAgICAgIHVybCwKICAgICAgICAgICAgaGVhZGVyOiB0aGlzLmhlYWRlcnMsCiAgICAgICAgICAgIGxyYzogbHlyaWMsCiAgICAgICAgICAgIGNvdmVyLAogICAgICAgICAgICBwaWM6IGNvdmVyLAogICAgICAgICAgICBoZWlnaHQ6IDcyMAogICAgICAgIH07CiAgICB9Cn07 \ No newline at end of file diff --git "a/spider/js/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" "b/spider/js_bad/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" similarity index 100% rename from "spider/js/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" rename to "spider/js_bad/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" diff --git "a/spider/js_dr2/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" "b/spider/js_dr2_old/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" similarity index 100% rename from "spider/js_dr2/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" rename to "spider/js_dr2_old/\347\247\215\345\255\220\351\237\263\344\271\220[\345\220\254].js" diff --git "a/spider/js_dr2/\347\261\263\345\205\224\351\237\263\344\271\220.js" "b/spider/js_dr2_old/\347\261\263\345\205\224\351\237\263\344\271\220.js" similarity index 100% rename from "spider/js_dr2/\347\261\263\345\205\224\351\237\263\344\271\220.js" rename to "spider/js_dr2_old/\347\261\263\345\205\224\351\237\263\344\271\220.js" diff --git "a/spider/js_dr2/\350\234\273\350\234\223FM[\345\220\254].js" "b/spider/js_dr2_old/\350\234\273\350\234\223FM[\345\220\254].js" similarity index 100% rename from "spider/js_dr2/\350\234\273\350\234\223FM[\345\220\254].js" rename to "spider/js_dr2_old/\350\234\273\350\234\223FM[\345\220\254].js" From d88ef787c99e751a303740e71268e06d781ee63b Mon Sep 17 00:00:00 2001 From: Taois Date: Wed, 21 Jan 2026 23:57:35 +0800 Subject: [PATCH 062/101] =?UTF-8?q?add:=20=E5=B0=9D=E8=AF=95=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0ds=E6=9C=AC=E5=9C=B0=E5=8C=85=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E4=B8=AD=E5=BF=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- controllers/web.js | 314 ++++++++++++++++++++++++++++++++++++++++++++- package.js | 12 +- package.json | 4 + package.py | 22 ++-- public/index.html | 3 +- 6 files changed, 342 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index f8488af2..89cdbf6f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ nodejs作为服务端的drpy实现。全面升级异步写法 ### 常用超链接 * [本项目主页-免翻](https://github.com/hjdhnx/drpy-node) -* [最新DS本地包-适配皮卡丘](/gh/release) +* ~~[最新DS本地包-适配皮卡丘](/gh/release)~~ +* [DS本地包下载中心](/admin/download) * [接口文档](docs/apidoc.md) | [接口列表如定时任务](docs/apiList.md) | ~~[小猫影视-待对接T4](https://github.com/waifu-project/movie/pull/135)~~ * [代码质量评估工具说明](docs/codeCheck.md) | [DS项目代码评估报告](docs/codeCheckReport.md) diff --git a/controllers/web.js b/controllers/web.js index ce58537a..9327d27c 100644 --- a/controllers/web.js +++ b/controllers/web.js @@ -1,9 +1,92 @@ -import {readFileSync, existsSync} from 'fs'; +import {readFileSync, existsSync, readdirSync, statSync} from 'fs'; +import {createReadStream} from 'fs'; +import {execSync} from 'child_process'; import path from 'path'; +import {fileURLToPath} from 'url'; +import {createHash} from 'crypto'; import {ENV} from '../utils/env.js'; import COOKIE from '../utils/cookieManager.js'; +import {validateBasicAuth} from '../utils/api_validate.js'; const COOKIE_AUTH_CODE = process.env.COOKIE_AUTH_CODE || 'drpys'; +const IS_VERCEL = process.env.VERCEL; +const DOWNLOAD_AUTH_SECRET = process.env.DOWNLOAD_AUTH_SECRET || 'drpys_download_secret'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const projectRootDir = path.dirname(__dirname); + +const generateDownloadToken = (filename) => { + const timestamp = Date.now(); + const data = `${filename}-${timestamp}-${DOWNLOAD_AUTH_SECRET}`; + const token = createHash('md5').update(data).digest('hex'); + return `${token}-${timestamp}`; +}; + +const validateDownloadToken = (filename, token) => { + if (!token) return false; + const parts = token.split('-'); + if (parts.length < 2) return false; + const timestamp = parseInt(parts.pop()); + const hash = parts.join('-'); + const data = `${filename}-${timestamp}-${DOWNLOAD_AUTH_SECRET}`; + const expectedHash = createHash('md5').update(data).digest('hex'); + const now = Date.now(); + return hash === expectedHash && (now - timestamp) < 3600000; +}; + +const findLatestPackage = (projectDir, packageName) => { + try { + const parentDir = path.dirname(projectDir); + const files = readdirSync(parentDir); + + const isGreen = packageName.includes('-green'); + const ext = packageName.split('.').pop(); + const baseName = packageName.replace(/-green\.[^.]+$/, '').replace(/\.[^.]+$/, ''); + const pattern = new RegExp(`^${baseName.replace(/\./g, '\\.')}-\\d{8}${isGreen ? '-green' : ''}\\.${ext}`); + + console.log(`查找包: ${packageName}, 正则: ${pattern.source}, 父目录: ${parentDir}`); + console.log('目录中的文件:', files.filter(f => f.includes('drpy-node'))); + + const packageFiles = files + .filter(file => pattern.test(file)) + .map(file => { + const filePath = path.join(parentDir, file); + const stats = statSync(filePath); + return {file, filePath, mtime: stats.mtime}; + }) + .sort((a, b) => b.mtime - a.mtime); + + console.log('匹配到的文件:', packageFiles.map(f => f.file)); + return packageFiles.length > 0 ? packageFiles[0] : null; + } catch (error) { + console.error('查找包失败:', error.message); + return null; + } +}; + +const buildPackage = (packageName) => { + try { + let command = 'node package.js'; + if (packageName.includes('-green')) { + command += ' -g'; + } + if (packageName.includes('.zip')) { + command += ' -z'; + } + + console.log(`执行打包命令: ${command}, 目录: ${projectRootDir}`); + const output = execSync(command, {cwd: projectRootDir, stdio: 'pipe'}); + console.log('打包输出:', output.toString()); + const result = findLatestPackage(projectRootDir, packageName); + console.log('打包后查找结果:', result ? result.file : '未找到'); + return result; + } catch (error) { + console.error('打包失败:', error.message); + console.error('错误详情:', error.stdout?.toString(), error.stderr?.toString()); + throw error; + } +}; export default (fastify, options, done) => { fastify.get('/admin/encoder', async (request, reply) => { @@ -75,5 +158,234 @@ export default (fastify, options, done) => { } }); + fastify.get('/admin/download', { + preHandler: validateBasicAuth + }, async (request, reply) => { + try { + if (IS_VERCEL) { + return reply.code(403).send({ + success: false, + message: 'Vercel 环境不支持文件下载功能', + }); + } + + const projectName = path.basename(projectRootDir); + + const files = [ + {name: `${projectName}.7z`, desc: '7z 压缩包(标准版)'}, + {name: `${projectName}.zip`, desc: 'ZIP 压缩包(标准版)'}, + {name: `${projectName}-green.7z`, desc: '7z 压缩包(绿色版,不含[密]文件)'}, + {name: `${projectName}-green.zip`, desc: 'ZIP 压缩包(绿色版,不含[密]文件)'} + ]; + + const html = ` + + + + + + 下载 ${projectName} + + + +

    ${projectName} 下载中心

    +
    链接已复制到剪贴板
    +
    + ${files.map(file => { + const token = generateDownloadToken(file.name); + const downloadUrl = `/admin/download/${file.name}?auth=${token}`; + return ` +
    +
    + ${file.name} +
    ${file.desc}
    +
    +
    + 下载 + +
    +
    `; + }).join('')} +
    + + +`; + + reply.type('text/html').send(html); + } catch (error) { + console.error('下载页面加载失败:', error.message); + return reply.code(500).send({ + success: false, + message: '加载下载页面失败', + error: error.message, + }); + } + }); + + fastify.get('/admin/download/:filename', { + preHandler: async (request, reply) => { + const {auth} = request.query; + if (validateDownloadToken(request.params.filename, auth)) { + return; + } + const authHeader = request.headers.authorization; + if (!authHeader) { + reply.header('WWW-Authenticate', 'Basic'); + return reply.code(401).send('Authentication required'); + } + const base64Credentials = authHeader.split(' ')[1]; + const credentials = Buffer.from(base64Credentials, 'base64').toString('utf-8'); + const [username, password] = credentials.split(':'); + const validUsername = process.env.API_AUTH_NAME || ''; + const validPassword = process.env.API_AUTH_CODE || ''; + if (username === validUsername && password === validPassword) { + return; + } + reply.header('WWW-Authenticate', 'Basic'); + return reply.code(401).send('Invalid credentials'); + } + }, async (request, reply) => { + try { + if (IS_VERCEL) { + return reply.code(403).send({ + success: false, + message: 'Vercel 环境不支持文件下载功能', + }); + } + + const {filename} = request.params; + const projectName = path.basename(projectRootDir); + + const validFilenames = [ + `${projectName}.7z`, + `${projectName}.zip`, + `${projectName}-green.7z`, + `${projectName}-green.zip` + ]; + + if (!validFilenames.includes(filename)) { + return reply.code(400).send({ + success: false, + message: '无效的文件名', + }); + } + + let latestPackage = findLatestPackage(projectRootDir, filename); + + if (!latestPackage) { + console.log(`未找到 ${filename},开始打包...`); + latestPackage = buildPackage(filename); + if (!latestPackage) { + return reply.code(500).send({ + success: false, + message: '打包失败,无法创建压缩文件', + }); + } + } + + const fileStream = createReadStream(latestPackage.filePath); + const contentType = filename.endsWith('.zip') ? 'application/zip' : 'application/x-7z-compressed'; + reply.header('Content-Type', contentType); + reply.header('Content-Disposition', `attachment; filename="${encodeURIComponent(latestPackage.file)}"`); + return reply.send(fileStream); + } catch (error) { + console.error('下载文件失败:', error.message); + return reply.code(500).send({ + success: false, + message: '下载失败', + error: error.message, + }); + } + }); + done(); }; diff --git a/package.js b/package.js index 6489562d..9cc52648 100644 --- a/package.js +++ b/package.js @@ -37,7 +37,7 @@ const filterGreenFiles = (scriptDir) => { }; // 压缩目录 -const compressDirectory = (scriptDir, green) => { +const compressDirectory = (scriptDir, green, useZip) => { const currentDir = basename(scriptDir); const currentTime = new Date().toLocaleDateString('zh-CN', { year: 'numeric', @@ -45,12 +45,13 @@ const compressDirectory = (scriptDir, green) => { day: '2-digit' }).replace(/\//g, ''); const archiveSuffix = green ? '-green' : ''; - const archiveName = `${currentDir}-${currentTime}${archiveSuffix}.7z`; + const archiveExt = useZip ? '.zip' : '.7z'; + const archiveName = `${currentDir}-${currentTime}${archiveSuffix}${archiveExt}`; const parentDir = resolve(scriptDir, '..'); const archivePath = join(parentDir, archiveName); - // 构建 7z 命令 + // 构建压缩命令参数 const excludeParams = []; // 排除目录 @@ -77,7 +78,7 @@ const compressDirectory = (scriptDir, green) => { } // 构建命令,打包目录内容而不包含目录本身 - const command = `7z a "${archivePath}" "${join(scriptDir, '*')}" -r ${excludeParams.join(' ')}`; + const command = `7z a -t${useZip ? 'zip' : '7z'} "${archivePath}" "${join(scriptDir, '*')}" -r ${excludeParams.join(' ')}`; console.log(`构建的 7z 命令: ${command}`); try { @@ -95,8 +96,9 @@ const main = () => { // 简单解析命令行参数 const args = process.argv.slice(2); const green = args.includes('-g') || args.includes('--green'); + const useZip = args.includes('-z') || args.includes('--zip'); - compressDirectory(scriptDir, green); + compressDirectory(scriptDir, green, useZip); }; main(); diff --git a/package.json b/package.json index e350953d..e7e77108 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,12 @@ "node22-win": "chcp 65001 && node --trace-deprecation --experimental-sqlite index.js", "package": "python package.py", "package-green": "python package.py -g", + "package-zip": "python package.py -z", + "package-green-zip": "python package.py -g -z", "packageJS": "node package.js", "packageJS-green": "node package.js -g", + "packageJS-zip": "node package.js -z", + "packageJS-green-zip": "node package.js -g -z", "gzip-1": "node controllers/encoder.js json/十六万歌曲.json", "ungzip-1": "node controllers/decoder.js json/十六万歌曲.json.gz", "moontv": "node scripts/mjs/moontv.mjs 采集2025.json -p" diff --git a/package.py b/package.py index d34e7011..9949858f 100644 --- a/package.py +++ b/package.py @@ -45,13 +45,14 @@ def filter_green_files(script_dir): return green_files -def generate_archive_name(script_dir, green=False): +def generate_archive_name(script_dir, green=False, use_zip=False): """ 生成压缩包文件名 Args: script_dir (str): 脚本所在目录 green (bool): 是否为green模式 + use_zip (bool): 是否使用ZIP格式 Returns: str: 压缩包的完整路径 @@ -64,7 +65,8 @@ def generate_archive_name(script_dir, green=False): # 根据是否传入 green 参数生成压缩包文件名 archive_suffix = "-green" if green else "" - archive_name = f"{current_dir}-{current_time}{archive_suffix}.7z" + archive_ext = ".zip" if use_zip else ".7z" + archive_name = f"{current_dir}-{current_time}{archive_suffix}{archive_ext}" # 压缩包输出路径 (脚本所在目录的外面) parent_dir = os.path.abspath(os.path.join(script_dir, "..")) @@ -108,7 +110,7 @@ def build_exclude_params(script_dir, green=False): return exclude_params -def execute_compression(archive_path, script_dir, exclude_params): +def execute_compression(archive_path, script_dir, exclude_params, use_zip=False): """ 执行7z压缩命令 @@ -116,9 +118,11 @@ def execute_compression(archive_path, script_dir, exclude_params): archive_path (str): 压缩包输出路径 script_dir (str): 脚本所在目录 exclude_params (list): 排除参数列表 + use_zip (bool): 是否使用ZIP格式 """ # 构建命令,打包目录内容而不包含目录本身 - command = f"7z a \"{archive_path}\" \"{script_dir}\\*\" " + " ".join(exclude_params) + archive_type = "zip" if use_zip else "7z" + command = f"7z a -t{archive_type} \"{archive_path}\" \"{script_dir}\\*\" " + " ".join(exclude_params) # 打印构建的命令进行调试 print(f"构建的 7z 命令: {command}") @@ -131,22 +135,23 @@ def execute_compression(archive_path, script_dir, exclude_params): print(f"压缩失败: {e}") -def compress_directory(script_dir, green=False): +def compress_directory(script_dir, green=False, use_zip=False): """ 压缩目录为7z包 Args: script_dir (str): 要压缩的目录路径 green (bool): 是否启用green模式,筛选带[密]的文件 + use_zip (bool): 是否使用ZIP格式 """ # 生成压缩包文件名和路径 - archive_path = generate_archive_name(script_dir, green) + archive_path = generate_archive_name(script_dir, green, use_zip) # 构建排除参数 exclude_params = build_exclude_params(script_dir, green) # 执行压缩 - execute_compression(archive_path, script_dir, exclude_params) + execute_compression(archive_path, script_dir, exclude_params, use_zip) if __name__ == "__main__": @@ -156,7 +161,8 @@ def compress_directory(script_dir, green=False): # 解析命令行参数 parser = argparse.ArgumentParser(description="压缩当前目录为 7z 包,支持可选参数。") parser.add_argument('-g', '--green', action='store_true', help="启用 green 模式,筛选 js 目录下所有带 [密] 的文件。") + parser.add_argument('-z', '--zip', action='store_true', help="使用 ZIP 格式打包,默认使用 7z 格式。") args = parser.parse_args() # 调用压缩函数 - compress_directory(script_dir, green=args.green) + compress_directory(script_dir, green=args.green, use_zip=args.zip) diff --git a/public/index.html b/public/index.html index 41ed026e..a580710f 100644 --- a/public/index.html +++ b/public/index.html @@ -14,7 +14,8 @@

    drpyS(drpy-node)

    常用超链接