diff --git a/core/huya/__init__.py b/core/huya/__init__.py index bfeb306..19c57f9 100644 --- a/core/huya/__init__.py +++ b/core/huya/__init__.py @@ -8,6 +8,9 @@ __all__ = [ "HuyaWssClient", "GetUserScoreReq", "GetUserScoreResp", + "HuyaVerificationError", + "HuyaVerificationSolver", + "solve_huya_verification", ] @@ -21,4 +24,14 @@ def __getattr__(name: str): } globals().update(values) return values[name] + if name in {"HuyaVerificationError", "HuyaVerificationSolver", "solve_huya_verification"}: + from .verification import HuyaVerificationError, HuyaVerificationSolver, solve_huya_verification + + values = { + "HuyaVerificationError": HuyaVerificationError, + "HuyaVerificationSolver": HuyaVerificationSolver, + "solve_huya_verification": solve_huya_verification, + } + globals().update(values) + return values[name] raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/core/huya/verification/__init__.py b/core/huya/verification/__init__.py new file mode 100644 index 0000000..a893d3f --- /dev/null +++ b/core/huya/verification/__init__.py @@ -0,0 +1,9 @@ +"""虎牙风控验证求解器。""" + +from .solver import HuyaVerificationError, HuyaVerificationSolver, solve_huya_verification + +__all__ = [ + "HuyaVerificationError", + "HuyaVerificationSolver", + "solve_huya_verification", +] diff --git a/core/huya/verification/models/best.onnx b/core/huya/verification/models/best.onnx new file mode 100644 index 0000000..70c302e Binary files /dev/null and b/core/huya/verification/models/best.onnx differ diff --git a/core/huya/verification/models/slider_2.onnx b/core/huya/verification/models/slider_2.onnx new file mode 100644 index 0000000..d3cd8a2 Binary files /dev/null and b/core/huya/verification/models/slider_2.onnx differ diff --git a/core/huya/verification/models/weights.onnx b/core/huya/verification/models/weights.onnx new file mode 100644 index 0000000..e5829c6 Binary files /dev/null and b/core/huya/verification/models/weights.onnx differ diff --git a/core/huya/verification/ocr.py b/core/huya/verification/ocr.py new file mode 100644 index 0000000..22f7718 --- /dev/null +++ b/core/huya/verification/ocr.py @@ -0,0 +1,248 @@ +"""虎牙滑块/点选验证码 OCR。""" + +from __future__ import annotations + +from functools import lru_cache +from io import BytesIO +from pathlib import Path + +import cv2 +import numpy as np +import onnxruntime as ort +from PIL import Image +from scipy.optimize import linear_sum_assignment + + +MODEL_DIR = Path(__file__).resolve().parent / "models" + + +class YoloOnnx: + """轻量 YOLO ONNX 推理封装。""" + + def __init__(self, model_path: str | Path, classes: list[str], providers: list[str] | None = None): + providers = providers or ["CPUExecutionProvider"] + ort.set_default_logger_severity(3) + self.session = ort.InferenceSession(str(model_path), providers=providers) + self.input_name = self.session.get_inputs()[0].name + self.output_name = self.session.get_outputs()[0].name + self.input_shape = self.session.get_inputs()[0].shape[2:] + self.names = classes + self.scale = 1.0 + self.pad_top = 0 + self.pad_left = 0 + + @staticmethod + def xywh2xyxy(value: np.ndarray) -> np.ndarray: + result = np.copy(value) + result[..., 0] = value[..., 0] - value[..., 2] / 2 + result[..., 1] = value[..., 1] - value[..., 3] / 2 + result[..., 2] = value[..., 0] + value[..., 2] / 2 + result[..., 3] = value[..., 1] + value[..., 3] / 2 + return result + + def preprocess(self, image: Image.Image) -> np.ndarray: + img = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) + height, width = img.shape[:2] + + self.scale = min(self.input_shape[0] / height, self.input_shape[1] / width) + new_size = (int(width * self.scale), int(height * self.scale)) + resized = cv2.resize(img, new_size, interpolation=cv2.INTER_LINEAR) + + dh = self.input_shape[0] - new_size[1] + dw = self.input_shape[1] - new_size[0] + self.pad_top = dh // 2 + pad_bottom = dh - self.pad_top + self.pad_left = dw // 2 + pad_right = dw - self.pad_left + + padded = cv2.copyMakeBorder( + resized, + self.pad_top, + pad_bottom, + self.pad_left, + pad_right, + cv2.BORDER_CONSTANT, + value=(114, 114, 114), + ) + input_tensor = padded.transpose(2, 0, 1).astype(np.float32) / 255.0 + return np.expand_dims(input_tensor, axis=0) + + @staticmethod + def nms(boxes: np.ndarray, scores: np.ndarray, iou_threshold: float = 0.3) -> list[int]: + order = scores.argsort()[::-1] + keep = [] + + while order.size > 0: + index = order[0] + keep.append(index) + + xx1 = np.maximum(boxes[index, 0], boxes[order[1:], 0]) + yy1 = np.maximum(boxes[index, 1], boxes[order[1:], 1]) + xx2 = np.minimum(boxes[index, 2], boxes[order[1:], 2]) + yy2 = np.minimum(boxes[index, 3], boxes[order[1:], 3]) + + width = np.maximum(0.0, xx2 - xx1) + height = np.maximum(0.0, yy2 - yy1) + intersection = width * height + area_i = (boxes[index, 2] - boxes[index, 0]) * (boxes[index, 3] - boxes[index, 1]) + area_j = (boxes[order[1:], 2] - boxes[order[1:], 0]) * ( + boxes[order[1:], 3] - boxes[order[1:], 1] + ) + iou = intersection / (area_i + area_j - intersection + 1e-7) + + inds = np.where(iou <= iou_threshold)[0] + order = order[inds + 1] + + return keep + + def postprocess( + self, + outputs: list[np.ndarray], + conf_threshold: float = 0.1, + iou_threshold: float = 0.3, + ) -> list[dict]: + predictions = np.squeeze(outputs[0]).T + class_scores = predictions[:, 4:] + scores = np.max(class_scores, axis=1) + class_ids = np.argmax(class_scores, axis=1) + + valid_indices = scores > conf_threshold + predictions = predictions[valid_indices] + scores = scores[valid_indices] + class_ids = class_ids[valid_indices] + if predictions.size == 0: + return [] + + boxes = predictions[:, :4].copy() + boxes[:, 0] = (boxes[:, 0] - self.pad_left) / self.scale + boxes[:, 1] = (boxes[:, 1] - self.pad_top) / self.scale + boxes[:, 2] /= self.scale + boxes[:, 3] /= self.scale + xyxy_boxes = self.xywh2xyxy(boxes) + + keep_indices = [] + for class_id in np.unique(class_ids): + class_indices = np.where(class_ids == class_id)[0] + class_keep = self.nms( + xyxy_boxes[class_indices], + scores[class_indices], + iou_threshold, + ) + keep_indices.extend(class_indices[class_keep]) + + results = [] + for index in keep_indices: + class_id = int(class_ids[index]) + x1, y1, x2, y2 = map(int, xyxy_boxes[index].tolist()) + results.append({ + "label_id": class_id, + "label_name": self.names[class_id], + "confidence": float(scores[index]), + "box_mid_xy": [(x1 + x2) // 2, (y1 + y2) // 2], + "xyxy": [x1, y1, x2, y2], + }) + + results.sort(key=lambda item: item["confidence"], reverse=True) + return results + + def detect(self, image: Image.Image) -> list[dict]: + input_tensor = self.preprocess(image) + outputs = self.session.run([self.output_name], {self.input_name: input_tensor}) + return self.postprocess(outputs) + + +class SimilarityOnnx: + """点选验证码中目标图和候选字的相似度模型。""" + + def __init__(self, model_path: str | Path, providers: list[str] | None = None): + providers = providers or ["CPUExecutionProvider"] + ort.set_default_logger_severity(3) + self.session = ort.InferenceSession(str(model_path), providers=providers) + self.input_shape = [64, 64] + + @staticmethod + def sigmoid(value: np.ndarray) -> np.ndarray: + return 1 / (1 + np.exp(-value)) + + @staticmethod + def _to_image(value) -> Image.Image: + if isinstance(value, np.ndarray): + return Image.fromarray(value) + if isinstance(value, bytes): + return Image.open(BytesIO(value)) + if isinstance(value, Image.Image): + return value + return Image.open(value) + + def _tensor(self, value) -> np.ndarray: + image = self._to_image(value).convert("RGB").resize(tuple(reversed(self.input_shape)), 1) + array = np.array(image).astype(np.float32) / 255.0 + return np.expand_dims(np.transpose(array, (2, 0, 1)), 0) + + def score(self, image_1, image_2) -> int: + out = self.session.run(None, {"x1": self._tensor(image_1), "x2": self._tensor(image_2)}) + similarity = self.sigmoid(out[0])[0][0] + return int(round(similarity.item(), 2) * 100) + + +class HuyaCaptchaOcr: + """封装虎牙滑块和点选识别。""" + + def __init__(self, model_dir: str | Path = MODEL_DIR, providers: list[str] | None = None): + model_dir = Path(model_dir) + self.similarity = SimilarityOnnx(model_dir / "weights.onnx", providers=providers) + self.click_model = YoloOnnx(model_dir / "best.onnx", classes=["target", "char"], providers=providers) + self.slider_model = YoloOnnx(model_dir / "slider_2.onnx", classes=["slider"], providers=providers) + + @staticmethod + def _open_image(image_bytes: bytes) -> Image.Image: + return Image.open(BytesIO(image_bytes)).convert("RGB") + + def ocr_slider_box(self, image_bytes: bytes) -> list[int]: + """识别滑块缺口框,返回 [x1, y1, x2, y2]。""" + image = self._open_image(image_bytes) + detections = self.slider_model.detect(image) + boxes = [item["xyxy"] for item in detections] + return boxes[0] if boxes else [100, 100, 100, 100] + + def ocr_click_points(self, image_bytes: bytes) -> list[list[int]]: + """识别点选坐标,返回按目标顺序排列的点击点。""" + image = self._open_image(image_bytes) + detections = self.click_model.detect(image) + results = [{**item, "cropped_image": image.crop(tuple(item["xyxy"]))} for item in detections] + + char_list = [item for item in results if item.get("label_name") == "char"] + target_list = [item for item in results if item.get("label_name") == "target"] + target_list = [item for item in target_list if item["xyxy"][2] - item["xyxy"][0] > 10] + char_list.sort(key=lambda item: item["xyxy"][0]) + target_list.sort(key=lambda item: item["xyxy"][0]) + + if not char_list or not target_list: + return [] + + score_matrix = np.zeros((len(target_list), len(char_list))) + for target_index, target in enumerate(target_list): + for char_index, char in enumerate(char_list): + try: + score_matrix[target_index][char_index] = -self.similarity.score( + target["cropped_image"], + char["cropped_image"], + ) + except Exception: + score_matrix[target_index][char_index] = 1e6 + + row_ind, col_ind = linear_sum_assignment(score_matrix) + matched = [] + for target_index, char_index in zip(row_ind, col_ind): + if score_matrix[target_index][char_index] == 1e6: + continue + char = char_list[char_index] + matched.append({**char, "index": target_index + 1}) + + return [item["box_mid_xy"] for item in matched] + + +@lru_cache(maxsize=1) +def default_ocr() -> HuyaCaptchaOcr: + """懒加载默认 OCR,避免导入 core.huya 时立即加载 150MB 模型。""" + return HuyaCaptchaOcr() diff --git a/core/huya/verification/solver.py b/core/huya/verification/solver.py new file mode 100644 index 0000000..4c0126b --- /dev/null +++ b/core/huya/verification/solver.py @@ -0,0 +1,388 @@ +"""虎牙登录风控验证闭环。""" + +from __future__ import annotations + +import base64 +import io +import json +import random +import time +from collections.abc import Mapping +from http.cookies import SimpleCookie +from urllib.parse import parse_qs, quote, urlparse + +import cv2 +import execjs +import numpy as np +import requests +from PIL import Image +from loguru import logger + +from .ocr import HuyaCaptchaOcr, default_ocr +from .track import format_track, generate_slide_track + + +DEFAULT_UA = ( + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/120.0.0.0 Safari/537.36" +) + + +class HuyaVerificationError(RuntimeError): + """虎牙风控验证失败。""" + + +def _cookie_mapping(cookie: Mapping[str, str] | str | None) -> dict[str, str]: + """兼容 dict 和 Cookie 字符串。""" + if not cookie: + return {} + if isinstance(cookie, str): + parsed = SimpleCookie() + parsed.load(cookie) + return {key: morsel.value for key, morsel in parsed.items()} + return {str(key): str(value) for key, value in cookie.items()} + + +class HuyaVerificationSolver: + """处理虎牙 returnCode=10030/10039 后的滑块或点选验证。""" + + def __init__( + self, + cookie: Mapping[str, str] | str | None = None, + ua: str = DEFAULT_UA, + sdid: str = "", + session: requests.Session | None = None, + ocr: HuyaCaptchaOcr | None = None, + proxies: Mapping[str, str] | None = None, + timeout: tuple[float, float] = (8, 20), + ): + self.cookie = _cookie_mapping(cookie) + self.ua = ua or DEFAULT_UA + self.sdid = sdid or self.cookie.get("sdid", "") + self.session = session or requests.Session() + self.session.trust_env = False + if self.cookie: + self.session.cookies.update(self.cookie) + if proxies: + self.session.proxies = dict(proxies) + self.session.headers.update({ + "Accept-Language": "zh-CN,zh;q=0.9", + "Cache-Control": "no-cache", + "Connection": "keep-alive", + "Origin": "https://aq.huya.com", + "Pragma": "no-cache", + "Referer": "https://aq.huya.com/", + "User-Agent": self.ua, + "accept": "application/json, text/plain, */*", + "content-type": "application/json", + }) + self.timeout = timeout + self.ocr = ocr or default_ocr() + + self.huyapk = "" + self.scene_type = "" + self.code = "" + self.url_param_map: dict[str, str] = {} + self.strategy_url = "" + self.js_ctx = None + + @staticmethod + def _auth_page_url() -> str: + """生成 auth 页面地址,形式参考易语言实现。""" + return f"https://aq.huya.com/p/udb_login.html?v={str(int(time.time() * 1000))[:8]}00000" + + @staticmethod + def _decode_image(base64_string: str | None) -> bytes: + if not base64_string: + raise HuyaVerificationError("验证码图片为空") + if ";base64," in base64_string: + base64_string = base64_string.split(";base64,")[-1] + return base64.b64decode(base64_string) + + @staticmethod + def _vertical_concat_align_left(bg_bytes: bytes, tip_bytes: bytes, image_format: str = "JPEG") -> bytes: + bg = cv2.imdecode(np.frombuffer(bg_bytes, np.uint8), cv2.IMREAD_COLOR) + tip = cv2.imdecode(np.frombuffer(tip_bytes, np.uint8), cv2.IMREAD_COLOR) + max_width = max(bg.shape[1], tip.shape[1]) + + def pad_right(img, target_width): + height, width = img.shape[:2] + if width >= target_width: + return img + return cv2.copyMakeBorder( + img, + 0, + 0, + 0, + target_width - width, + cv2.BORDER_CONSTANT, + value=(255, 255, 255), + ) + + concat_img = np.vstack([pad_right(tip, max_width), pad_right(bg, max_width)]) + success, buffer = cv2.imencode(f".{image_format.lower()}", concat_img) + if not success: + raise HuyaVerificationError("点选验证码图片编码失败") + return buffer.tobytes() + + @staticmethod + def _remove_black_borders(image: Image.Image) -> tuple[Image.Image, int]: + if image.mode != "RGBA": + image = image.convert("RGBA") + bbox = image.getbbox() + if not bbox: + return image, 0 + cropped_height = bbox[3] - bbox[1] + black_border_height = image.height - cropped_height + return image.crop(bbox), black_border_height + + @classmethod + def _composite_slider_images(cls, bg_bytes: bytes, tip_bytes: bytes, y_position: int) -> bytes: + bg = Image.open(io.BytesIO(bg_bytes)).convert("RGB") + tip = Image.open(io.BytesIO(tip_bytes)).convert("RGBA") + tip, black_border_height = cls._remove_black_borders(tip) + adjusted_y = y_position + int(black_border_height / 2) + 1 + bg.paste(tip, (10, adjusted_y), tip) + output = io.BytesIO() + bg.save(output, format="PNG") + return output.getvalue() + + @staticmethod + def _opencv_slider_x(target_bytes: bytes, background_bytes: bytes) -> int: + target = cv2.imdecode(np.frombuffer(target_bytes, np.uint8), cv2.IMREAD_ANYCOLOR) + background = cv2.imdecode(np.frombuffer(background_bytes, np.uint8), cv2.IMREAD_ANYCOLOR) + target = cv2.cvtColor(cv2.Canny(target, 100, 200), cv2.COLOR_GRAY2RGB) + background = cv2.cvtColor(cv2.Canny(background, 100, 200), cv2.COLOR_GRAY2RGB) + result = cv2.matchTemplate(background, target, cv2.TM_CCOEFF_NORMED) + _, _, _, max_loc = cv2.minMaxLoc(result) + return int(max_loc[0]) + + def _request_json(self, method: str, url: str, **kwargs) -> dict: + response = self.session.request(method, url, timeout=self.timeout, **kwargs) + response.raise_for_status() + try: + return response.json() + except json.JSONDecodeError as exc: + raise HuyaVerificationError(f"虎牙验证接口返回不是 JSON: {response.text[:200]}") from exc + + def _compile_js(self, dx_js: str) -> None: + js_data = """ + window = globalThis; + $$self_js$$ + + function get_regoin_arr(segment, huyapk) { + return JSON.parse(atob(window.UdbCipher.decrypt(segment, huyapk))).ord + } + function get_act(act_data, huyapk) { + act_data = encodeURI(JSON.stringify(act_data)) + return window.UdbCipher.encrypt(btoa(act_data), huyapk) + } + """ + self.js_ctx = execjs.compile(js_data.replace("$$self_js$$", dx_js)) + + def _build_common_payload(self, extra: dict) -> dict: + payload = { + "urlParamMap": self.url_param_map, + "wupData": "", + "page": self._auth_page_url(), + "behavior": "%5B%5D", + "info": self.sdid, + } + payload.update(extra) + return {"appId": "5002", "data": payload} + + @staticmethod + def _extract_strategy_url(challenge_payload: dict | str) -> str: + """兼容完整响应、data 子对象、data URL 字符串三种输入。""" + if isinstance(challenge_payload, str): + return challenge_payload + + data = challenge_payload.get("data") + if isinstance(data, str) and data.startswith("http"): + return data + if isinstance(data, str): + try: + data = json.loads(data) + except json.JSONDecodeError: + data = {} + + strategy_root = data if isinstance(data, dict) else challenge_payload + try: + return strategy_root["strategys"][0]["data"] + except (KeyError, IndexError, TypeError) as exc: + raise HuyaVerificationError("虎牙响应中没有 strategys[0].data") from exc + + def _parse_strategy(self, challenge_payload: dict | str) -> None: + strategy_url = self._extract_strategy_url(challenge_payload) + + query_params = parse_qs(urlparse(strategy_url).query) + self.url_param_map = {key: value[0] for key, value in query_params.items()} + self.scene_type = self.url_param_map.get("sceneType", "") + self.strategy_url = strategy_url + if not self.url_param_map.get("param"): + raise HuyaVerificationError("虎牙验证链接缺少 param") + + def _restore_slider_background(self, bg_bytes: bytes, segment: str, huyapk: str) -> bytes: + recover_list = self.js_ctx.call("get_regoin_arr", segment, huyapk) + image = Image.open(io.BytesIO(bg_bytes)).convert("RGB") + width, height = image.size + captcha = Image.new("RGB", (width, height)) + for index, region_index in enumerate(recover_list): + region = image.crop((region_index * 26, 0, region_index * 26 + 26, 180)) + captcha.paste(region, (index * 26, 0, index * 26 + 26, 180)) + output = io.BytesIO() + captcha.save(output, format="JPEG") + return output.getvalue() + + def _get_track_point(self, url: str, payload: dict): + result = self._request_json("post", url, json=payload) + if result.get("returnCode") != 0 or not result.get("data", {}).get("code"): + raise HuyaVerificationError(f"获取验证码图片失败: {result}") + + data = result["data"] + self.code = data["code"] + self.huyapk = data["huyapk"] + segment = data.get("segment") + if segment: + logger.info("虎牙验证类型: 滑块") + bg_bytes = self._decode_image(data.get("dtuStr")) + tip_bytes = self._decode_image(data.get("puzzleStr")) + restored_bg = self._restore_slider_background(bg_bytes, segment, self.huyapk) + composite = self._composite_slider_images(restored_bg, tip_bytes, int(data.get("location_y") or 0)) + slider_box = self.ocr.ocr_slider_box(composite) + yolo_x = int(slider_box[0] - 13) + opencv_x = self._opencv_slider_x(tip_bytes, restored_bg) + if abs(opencv_x - yolo_x) < 10: + return int((opencv_x + yolo_x) / 2) + return yolo_x + + logger.info("虎牙验证类型: 点选") + bg_bytes = self._decode_image(data.get("dTuStr")) + tip_bytes = self._decode_image(data.get("hZiStr")) + merged = self._vertical_concat_align_left(bg_bytes, tip_bytes) + points = self.ocr.ocr_click_points(merged) + return [[int(x), int(y) - 44] for x, y in points] + + def _send_slider_verify(self, url: str, point: int) -> dict: + track_points = generate_slide_track(point) + act_data = { + "point": int(point), + "travel": format_track(track_points), + "code": self.code, + "sceneType": self.scene_type, + "endTime": int(track_points[-1][-1]) - int(track_points[0][-1]), + } + act = self.js_ctx.call("get_act", act_data, self.huyapk) + behavior = quote( + json.dumps([{ + "action": "mousedown", + "id": "", + "txt": "", + "clientX": track_points[0][0], + "clientY": track_points[0][1], + "clientWidth": 350, + "clientHeight": 268, + "isTrusted": True, + "timeStamp": 1829, + "nowTime": int(time.time() * 1000), + }], separators=(",", ":")), + safe="~()*!.'", + ) + payload = self._build_common_payload({"behavior": behavior, "act": act, "ver": 5}) + return self._submit_verify(url, payload) + + def _send_click_verify(self, url: str, points: list[list[int]]) -> dict: + if not points: + raise HuyaVerificationError("点选坐标识别为空") + + start_time = int(time.time() * 1000) - random.randint(5000, 10000) + click_data = [] + current_time = start_time + for point in points: + current_time += random.randint(1000, 2000) + click_data.append([int(point[0]), int(point[1]), current_time]) + + interval_time_list = [item[-1] for item in click_data] + act_data = { + "clickData": ",".join(f"{x}_{y}" for x, y in points), + "intervalTime": "_".join(map(str, interval_time_list)), + "endTime": interval_time_list[-1] - interval_time_list[0], + "sceneType": self.scene_type, + "code": self.code, + } + act = self.js_ctx.call("get_act", act_data, self.huyapk) + + txt_list = ["", "1", "1\\n2"] + behavior_list = [] + for index, item in enumerate(click_data): + behavior_list.append({ + "action": "mousedown", + "id": "", + "txt": txt_list[index] if index < len(txt_list) else "", + "clientX": item[0], + "clientY": item[1], + "clientWidth": 350, + "clientHeight": 268, + "isTrusted": True, + "timeStamp": random.randint(2000, 5000), + "nowTime": item[2], + }) + + behavior = quote(json.dumps(behavior_list, separators=(",", ":")), safe="~()*!.'") + payload = self._build_common_payload({"behavior": behavior, "act": act, "ver": 5}) + return self._submit_verify(url, payload) + + def _submit_verify(self, url: str, payload: dict) -> dict: + body = json.dumps(payload, separators=(",", ":")) + result = self._request_json("post", url, params={"lock": "true"}, data=body) + return result.get("data") or result + + def _solve_current_strategy(self) -> dict: + """提交当前 strategy_url 对应的验证。""" + config_payload = self._build_common_payload({"cTuIndex": 0}) + config = self._request_json("post", "https://udbrtt.huya.com/auth/client/config3", json=config_payload) + try: + gurl = config["data"]["gurl"] + vurl = config["data"]["vurl"] + dx_js = config["data"]["js"] + except KeyError as exc: + raise HuyaVerificationError(f"config3 取参失败: {config}") from exc + + self._compile_js(dx_js) + point = self._get_track_point(gurl, config_payload) + logger.debug(f"虎牙验证识别结果: {point}") + if isinstance(point, list): + return self._send_click_verify(vurl, point) + return self._send_slider_verify(vurl, int(point)) + + def solve(self, challenge_payload: dict | str) -> dict: + """提交虎牙风控验证,返回 vurl 响应中的 data。""" + self._parse_strategy(challenge_payload) + result = self._solve_current_strategy() + + next_auth_url = result.get("nextAuthUrl") if isinstance(result, dict) else None + if next_auth_url: + logger.info("虎牙滑块后继续点选验证") + self._parse_strategy(next_auth_url) + result = self._solve_current_strategy() + return result + + +def solve_huya_verification( + challenge_payload: dict | str, + cookie: Mapping[str, str] | str | None = None, + ua: str = DEFAULT_UA, + sdid: str = "", + session: requests.Session | None = None, + proxies: Mapping[str, str] | None = None, +) -> dict: + """函数式入口,便于登录流程直接调用。""" + solver = HuyaVerificationSolver( + cookie=cookie, + ua=ua, + sdid=sdid, + session=session, + proxies=proxies, + ) + return solver.solve(challenge_payload) diff --git a/core/huya/verification/track.py b/core/huya/verification/track.py new file mode 100644 index 0000000..ca16f6b --- /dev/null +++ b/core/huya/verification/track.py @@ -0,0 +1,45 @@ +"""虎牙滑块轨迹生成工具。""" + +from __future__ import annotations + +import random +import time +from collections.abc import Iterable + + +def ease_out_expo(sep: float) -> float: + """缓出曲线,让轨迹更接近人工拖动。""" + if sep == 1: + return 1 + return 1 - pow(2, -10 * sep) + + +def generate_slide_track(distance: int) -> list[list[int]]: + """生成虎牙滑块验证所需 travel 轨迹。""" + if not isinstance(distance, int) or distance < 0: + raise ValueError(f"distance 必须是大于等于 0 的整数: {distance!r}") + + distance = distance + random.randint(10, 40) + current_time = int(time.time() * 1000) - random.randint(1500, 2000) + slide_x = random.randint(56, 63) + slide_y = random.randint(210, 213) + track = [[slide_x, slide_y, current_time]] + + count = random.randint(40, 60) + last_x = 0 + for index in range(count): + x = round(ease_out_expo(index / count) * distance) + current_time += random.randint(10, 20) + if x == last_x: + continue + y = random.randint(-1, 1) + track.append([x + slide_x, y + slide_y, current_time]) + last_x = x + + track.append(track[-1]) + return track + + +def format_track(points: Iterable[Iterable[int]]) -> str: + """把轨迹点格式化成虎牙 actData.travel 字符串。""" + return ";".join(f"{x},{y},{t}" for x, y, t in points) diff --git a/e 皮肤兑换与充值.txt b/e 皮肤兑换与充值.txt deleted file mode 100644 index 842e777..0000000 --- a/e 皮肤兑换与充值.txt +++ /dev/null @@ -1,2538 +0,0 @@ -.版本 2 -.支持库 edroptarget -.支持库 iext -.支持库 EThread -.支持库 spec - -.程序集 窗口程序集_窗口1 -.程序集变量 集句柄, 整数型 -.程序集变量 工作中, 逻辑型 -.程序集变量 工作线程池EX, 鱼刺类_线程池Ex -.程序集变量 工作线程取token, 鱼刺类_线程池Ex -.程序集变量 ww, 未闻花名花见皮肤 -.程序集变量 导出存放文件名, 文本型 - -.子程序 _窗口1_创建完毕 - -ww.皮肤加载 (2, , , , 真) -网络版授权验证 (假, “f28ba622a3ef3abf0a419f5cd6b548396dbcd7bd0d25fc815b6256be1db23421d3a329637cdb54f61e492184d1602670dff739ec7bd2847d67b98f0bff373646”) -.如果真 (信息框 (“此程序仅用于学习、技术交流,请勿用于非法!如出现任何问题后果自负!” + #换行符 + “ ”, #确认取消钮, “免责声明!!!”, ) = #取消钮) - 结束 () -.如果真结束 - -全目录临时 = 取运行目录 () + “\XYZ\临时” -全目录状态 = 取运行目录 () + “\XYZ\数据状态” -全PIC = 取运行目录 () + “\XYZ\生成订单图片” -全目录导出 = 取运行目录 () + “\XYZ\导出” -.如果真 (文件是否存在 (全目录临时) = 假) - 目录_创建 (全目录临时) -.如果真结束 -.如果真 (文件是否存在 (全目录状态) = 假) - 目录_创建 (全目录状态) -.如果真结束 -.如果真 (文件是否存在 (全PIC) = 假) - 目录_创建 (全PIC) -.如果真结束 -.如果真 (文件是否存在 (全目录导出) = 假) - 目录_创建 (全目录导出) -.如果真结束 - -拖放对象1.注册拖放控件 (超级列表框1.取窗口句柄 ()) -状态条1.置文本 (0, “双击列表指定数据行,查询账号详情....”) -数据写入列表 () -启动线程 (&商品列表, , ) -Gdip开始 () -配置_读取_易语言组件 (窗口1) - -.子程序 _超级列表框1_右键单击表项 - -弹出菜单 (菜单, , ) - -.子程序 _拖放对象1_得到文件 -.参数 接收到的文件路径, 文本型 -.局部变量 i, 文本型 -.局部变量 第一次分割, 文本型, , "0" -.局部变量 第二次分割, 文本型, , "3" -.局部变量 N, 整数型 -.局部变量 索引, 整数型 -.局部变量 计次1, 整数型 -.局部变量 计次2, 整数型 -.局部变量 临时数组, 文本型, , "0" -.局部变量 文本数组, 文本型, , "0" - -i = 到文本 (读入文件 (接收到的文件路径)) -文本数组 = 分割文本 (i, #换行符, ) -.计次循环首 (取数组成员数 (文本数组), 计次1) - 系统_处理事件 () - 索引 = 超级列表框1.插入表项 (, , , , , ) - 超级列表框1.置标题 (索引, 0, 到文本 (索引 + 1)) - 超级列表框1.置标题 (索引, 1, 文本数组 [计次1]) - 超级列表框1.置状态图片 (索引, 1) - 系统_处理事件 () -.计次循环尾 () -超级列表框1.允许重画 () ' 恢复自动重画 -超级列表框1.发送信息 (277, 7, 0) ' 显示最后一行 -清除数组 (文本数组) - -.子程序 _删除当前_被选择 -.局部变量 i, 整数型 -.局部变量 局_保存文本, 鱼刺类_输出文本 -.局部变量 局_保存目录, 文本型 - -超级列表框1.删除表项 (超级列表框1.现行选中项) -.计次循环首 (超级列表框1.取表项数 (), i) - 系统_处理事件 () - 超级列表框1.置标题 (i - 1, 0, 到文本 (i)) -.计次循环尾 () -.计次循环首 (超级列表框1.取表项数 (), i) - 系统_处理事件 () - 超级列表框1.置状态图片 (i - 1, 1) - 超级列表框1.置标题 (i - 1, 0, 到文本 (i)) -.计次循环尾 () - - -.子程序 _删除勾选_被选择 -.局部变量 表项数, 整数型 -.局部变量 m, 整数型 -.局部变量 i, 整数型 -.局部变量 局_保存目录, 文本型 -.局部变量 局_保存文本, 鱼刺类_输出文本 - -表项数 = 超级列表框1.取表项数 () -.计次循环首 (表项数, m) - 系统_处理事件 () - .如果真 (超级列表框1.取当前状态图片 (表项数 - m) = 1) - 超级列表框1.删除表项 (表项数 - m) - .如果真结束 - -.计次循环尾 () -.计次循环首 (超级列表框1.取表项数 (), i) - 系统_处理事件 () - 超级列表框1.置状态图片 (i - 1, 1) - 超级列表框1.置标题 (i - 1, 0, 到文本 (i)) -.计次循环尾 () - - -.子程序 _清空CK_被选择 -.局部变量 局_保存目录, 文本型 - -超级列表框1.全部删除 () -局_保存目录 = 取运行目录 () + “\斗鱼CK\” + 时间_格式化 (取现行时间 (), “MM.dd-”) + “斗鱼CK.txt” -删除文件 (局_保存目录) - -.子程序 _按钮_刷新商品_被单击 - -启动线程 (&商品列表, , ) - -.子程序 商品列表 -.局部变量 str, 文本型 -.局部变量 yyjson, json对象 -.局部变量 价格, 文本型 -.局部变量 N, 整数型 -.局部变量 commodityName, 文本型 -.局部变量 commodityId, 文本型 -.局部变量 列表NUM, 整数型 - -' 20240827 的 manualID=nZyNEyQwpP6bX -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/wgapi/ordnc/activity/peace/storehome?manualID=G4KA4Qnz4LDp7&rid=9263298”, , , , , “Host: www.douyu.com” + #换行符 + “Connection: keep-alive” + #换行符 + “sec-ch-ua: ” + #引号 + “Not_A Brand” + #引号 + “;v=” + #引号 + “8” + #引号 + “, ” + #引号 + “Chromium” + #引号 + “;v=” + #引号 + “120” + #引号 + “, ” + #引号 + “Google Chrome” + #引号 + “;v=” + #引号 + “120” + #引号 + “” + #换行符 + “Accept: application/json, text/plain, */*” + #换行符 + “sec-ch-ua-mobile: ?0” + #换行符 + “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” + #换行符 + “sec-ch-ua-platform: ” + #引号 + “Windows” + #引号 + “” + #换行符 + “Sec-Fetch-Site: same-origin” + #换行符 + “Sec-Fetch-Mode: cors” + #换行符 + “Sec-Fetch-Dest: empty” + #换行符 + “Referer: https://www.douyu.com/pages/live-peace-handbook/web/shop?ditchname=pass0&roomId=9263298”)) -yyjson.清空 () -.如果真 (yyjson.解析 (str) = 假) - 提示框 (“商品列表解析失败”, , , , 2000) - 返回 () - -.如果真结束 - -组合框1.清空 () -状态条1.置文本 (0, “正在刷新列表商品....”) -.计次循环首 (yyjson.取成员数 (“data/list”), N) - commodityId = yyjson.取文本 (“data/list/” + 到文本 (N - 1) + “/commodityId”) - commodityName = yyjson.取文本 (“data/list/” + 到文本 (N - 1) + “/commodityName”) - 价格 = yyjson.取文本 (“data/list/” + 到文本 (N - 1) + “/score”) - 组合框1.插入项目 (N - 1, commodityName + “一” + 价格 + “一” + commodityId, ) - 系统_处理事件 () -.计次循环尾 () -组合框1.现行选中项 = 0 -状态条1.置文本 (0, “列表商品刷新完成”) - -.子程序 _获取绑定二维码_被选择 - -启动线程 (&取二维码, , ) - -.子程序 取二维码 -.局部变量 ctn1, 文本型 -.局部变量 返回CK, 文本型 -.局部变量 局ID, 文本型 -.局部变量 str2, 文本型 -.局部变量 局_CK, 文本型 -.局部变量 str, 文本型 -.局部变量 局_CCK, 文本型 -.局部变量 ctn2, 文本型 -.局部变量 manualID, 文本型 -.局部变量 actAlias, 文本型 -.局部变量 str3, 文本型 -.局部变量 yyjson, json对象 -.局部变量 绑定url, 文本型 -.局部变量 局_文本, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 绑定游戏昵称, 文本型 -.局部变量 局_斗鱼昵称, 文本型 -.局部变量 图片句柄, 整数型 - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_斗鱼昵称 = 局_F [1] -局_CCK = 局_F [3] - -str = 到文本 (网页_访问_对象 (“https://www.douyu.com/curl/csrfApi/getCsrfCookie?”, , , 局_CCK, 返回CK, #常量1)) -' 调试输出 (局_CCK, 返回CK) -' 调试输出 (str) -状态条1.置文本 (0, “生成1-> ” + str) -ctn1 = 文本_取出中间文本 (返回CK, “acf_ccn=”, “;”) -.如果 (ctn1 ≠ “”) - str2 = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/wgapi/livenc/asubscribe/userSubStatus”, 1, “subscribe=cmn&ctn=” + ctn1, 返回CK, 局_CK, #常量1)) - 状态条1.置文本 (0, “生成二维码-> ” + str2) - ' 调试输出 (str2) - .如果 (寻找文本 (str2, “error” + #引号 + “:0”, , 假) ≠ -1) - ctn2 = 文本_取出中间文本 (局_CK, “acf_ccn=”, “;”) - ' 调试输出 (“ctn2---”, ctn2) - 全临界.进入 () - 超级列表框1.置标题 (超级列表框1.现行选中项, 5, ctn2) - 全临界.退出 () - - manualID = “XopK0bEg4ywwA” - actAlias = “20250213NQCYX” - - str3 = 到文本 (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/tencent/roleParam”, 1, “actAlias=” + actAlias + “&ctn=” + ctn2, 局_CCK, , #常量3)) - ' 调试输出 (str3) - yyjson.清空 () - yyjson.解析 (str3) - 绑定url = yyjson.取文本 (“data/url”) - ' 调试输出 (“绑定url-> ”, 绑定url) - .如果 (绑定url = “”) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “获取二维码失败”) - - .否则 - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “绑定二维码已生成”) - ' 图片框3.图片 = 文转图片E (局_斗鱼昵称) - 图片框1.图片 = 文本生成二维码图片 (绑定url, , , , , 10) - 状态条1.置文本 (1, “斗鱼名:” + 局_斗鱼昵称) - - 绑定游戏昵称 = 检测是否绑定游戏账号 (局_CCK) - 窗口_置信息3 (超级列表框1.现行选中项, 1, 绑定游戏昵称) - 检测账号 (局_CK, ctn2) - .如果结束 - - - .否则 - 窗口_置状态信息 (超级列表框1.现行选中项, 2, str2) - .如果结束 - -.否则 - 窗口_置状态信息 (超级列表框1.现行选中项, 2, 编码_usc2到ansi (str)) -.如果结束 - - -.子程序 检测账号, , , 通过兑换检测账号 -.参数 参_cook, 文本型 -.参数 参_ctn, 文本型 -.局部变量 局_文本, 文本型 -.局部变量 ctnEX, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_Cookie, 文本型 -.局部变量 str, 文本型 -.局部变量 局_xy, 文本型 -.局部变量 商品表, 文本型 -.局部变量 商品组, 文本型, , "0" -.局部变量 要兑换的商品名称, 文本型 -.局部变量 要兑换的商品价格, 文本型 -.局部变量 要兑换的商品ID, 文本型 -.局部变量 roleName, 文本型 -.局部变量 str2, 文本型 -.局部变量 局_bin, 字节集 -.局部变量 生成者, 文本型 -.局部变量 优化价格, 文本型 -.局部变量 areaName, 文本型 -.局部变量 platName, 文本型 -.局部变量 msg, 文本型 - -商品表 = 组合框1.取项目文本 (组合框1.现行选中项) -商品组 = 分割文本 (商品表, “一”, ) -.如果真 (取数组成员数 (商品组) < 3) - 状态条1.置文本 (0, “商品格式错误x”) - 返回 () -.如果真结束 - - -' 要兑换的商品名称 = 商品组 [1] -' 要兑换的商品价格 = 商品组 [2]nZALooPn0kZPW&ditchname=pass0&roomId=999 -要兑换的商品ID = 商品组 [3] -窗口_置状态信息 (超级列表框1.现行选中项, 2, “检测账号...”) -状态条1.置文本 (0, “正在检测账号-> ”) -' manualID=G4KA4Qnz4LDp7 -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/wgapi/ordnc/activity/peace/exchange”, 1, “manualID=nZyNEyQwpP6bX&rid=999&commodityID=” + 要兑换的商品ID + “&token%5Berror%5D%5Bcode%5D=-1&token%5Bdata%5D=&ctn=” + 参_ctn, 参_cook + “; acf_ccn=” + 参_ctn, , #常量7, 局_xy)) -' 调试输出 (取程序名称 (1), str) -状态条1.置文本 (0, “检测账号:” + str) -.如果真 (寻找文本 (str, “需要开通精英手册”, , 假) ≠ -1 或 寻找文本 (str, “服务器繁忙”, , 假) ≠ -1 或 寻找文本 (str, “不在时间范围内”, , 假) ≠ -1) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “账号有效”) - ' ’str2 = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/tencent/bindInfo?actAlias=20220616CJSZU”, , , 参_cook, , #常量3)) - 返回 () -.如果真结束 - - -' msg = 文本_取出中间文本 (str, “msg” + #引号 + “:” + #引号, #引号) -.' 如果真 (msg = “”) - ' 窗口_置状态信息 (超级列表框1.现行选中项, 2, “账号异常”) - ' 返回 () -.如果真结束 - -窗口_置状态信息 (超级列表框1.现行选中项, 2, “账号异常:” + str) - -.子程序 检测是否绑定游戏账号, 文本型 -.参数 参_CK, 文本型 -.局部变量 str, 文本型 -.局部变量 roleName, 文本型 - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/v2/tencent/bindInfo?actAlias=cjm”, , , 参_CK, , #常量3)) - -状态条1.置文本 (0, “查绑游戏名-> ” + str) -' {"error":0,"msg":"success","data":{"bindAccount":1,"bindRole":1,"bindAct":1,"needBindRole":null,"txAct":{"txActId":2811,"gameId":"cjm","gameName":"和平精英","bindType":1},"gameAccount":{"bindType":2,"type":"","faceuri":"https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTI4cIOxb4f7vpSkqYCIIvY1EJTgkhS0ZhVzzJSl2LzDpUzVBJKiaDjvuzpdS6cadAvA6bnrYwZ7jlQ/132","nick":"zicoo"},"gameRole":{"roleName":"白菜被拱了呀","areaName":"微信","platName":"安卓(android)","partitionName":""},"isGranted":null,"gameAuthScene":null,"canChangeRole":0,"changeRoleWaitTime":2490528},"redirectUrl":null} - -roleName = 文本_取出中间文本 (str, “roleName” + #引号 + “:” + #引号, #引号) -.如果真 (roleName ≠ “”) - 返回 (roleName) -.如果真结束 - -返回 (“NULL”) - -.子程序 _确认绑定_被选择 - -启动线程 (&完成绑定, , ) - -.子程序 完成绑定 -.局部变量 str2, 文本型 -.局部变量 cvl_csrf_token, 文本型 -.局部变量 局_文本, 文本型 -.局部变量 str, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 返回CK, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 绑定游戏昵称, 文本型 -.局部变量 msg, 文本型 -.局部变量 ctnEX, 文本型 -.局部变量 返回游戏name, 文本型 -.局部变量 str_0, 文本型 -.局部变量 roleName, 文本型 -.局部变量 nick, 文本型 -.局部变量 areaName, 文本型 -.局部变量 platName, 文本型 - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -ctnEX = 超级列表框1.取标题 (超级列表框1.现行选中项, 5) - -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_Cookie = 局_F [3] -' https://www.douyu.com/japi/carnivalApi/v2/tencent/bindInfo?actAlias=20260120QYOOB -' 这个是新版的号得查询’str_0 = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/v2/tencent/bindInfo?actAlias=20260120QYOOB”, , , 局_Cookie, , #常量3)) - -str_0 = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/v2/tencent/bindInfo?actAlias=cjm”, , , 局_Cookie, , #常量3)) -调试输出 (“str_0---”, str_0) -roleName = 文本_取出中间文本 (str_0, “roleName” + #引号 + “:” + #引号, #引号) -nick = 文本_取出中间文本 (str_0, “nick” + #引号 + “:” + #引号, #引号) -areaName = 文本_取出中间文本 (str_0, “areaName” + #引号 + “:” + #引号, #引号) -platName = 文本_取出中间文本 (str_0, “platName” + #引号 + “:” + #引号, #引号) - -标签_状态.标题 = “昵称:” + nick + #换行符 + “游戏名称:” + roleName + #换行符 + “平台:” + areaName + #换行符 + “手机:” + platName -.如果真 (信息框 (“是否绑定:” + roleName, #确认取消钮, , ) = #取消钮) - 提示框 (“取消绑定:” + roleName, , , , 1000) - 返回 () -.如果真结束 - - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnival/nc/common/generateCsrf”, 1, “{}”, 局_Cookie, 返回CK, #常量3)) - -cvl_csrf_token = 文本_取出中间文本 (返回CK, “cvl_csrf_token=”, “;”) -状态条1.置文本 (0, “取token-> ” + str) -' 调试输出 (cvl_csrf_token) -' 输出调试 (“cvl_csrf_token-”, cvl_csrf_token) -.如果真 (cvl_csrf_token = “”) - 窗口_置状态信息 (超级列表框1.现行选中项, 1, str) - 返回 () -.如果真结束 - -' 确认绑定 -str2 = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/tencent/bind”, 1, “actAlias=20260120QYOOB&csrfToken=” + cvl_csrf_token, 局_Cookie + “; cvl_csrf_token=” + cvl_csrf_token, , #常量3)) -状态条1.置文本 (0, “确认绑定-> ” + str2) -' 调试输出 (str2) -.如果真 (寻找文本 (str2, “error” + #引号 + “:0”, , 假) ≠ -1) - 窗口_置状态信息 (超级列表框1.现行选中项, 1, nick + “:绑定成功,生成二维码”) - 程序_延时 (500) - 窗口_置信息3 (超级列表框1.现行选中项, 1, roleName) - 程序_延时 (1000) - 精英二维码30 (ctnEX, 局_Cookie) - 返回 () -.如果真结束 - -msg = 文本_取出中间文本 (str2, “msg” + #引号 + “:” + #引号, #引号) -窗口_置状态信息 (超级列表框1.现行选中项, 1, msg) -信息框 (msg, 0, , ) - -' 绑定成功 {"error":0,"msg":"success","data":null,"redirectUrl":null} -' {"error":1006,"msg":"CSRF校验不通过!","data":null} -' {"error":-200001,"msg":"当前账号处于换绑周期冷却期,不可换绑","data":{},"redirectUrl":null} -' 输出调试 (“str5确认绑定-”, str5) - -.子程序 精英二维码30 -.参数 参_ctn, 文本型 -.参数 参_Cookie, 文本型 -.局部变量 str, 文本型 -.局部变量 str2, 文本型 -.局部变量 yyjson, json对象 -.局部变量 付款30链接, 文本型 - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/oms/web/peace/item”, 1, “{” + #引号 + “itemId” + #引号 + “:1,” + #引号 + “ctn” + #引号 + “:” + #引号 + 参_ctn + #引号 + “}”, 参_Cookie + “; ” + “acf_ccn=” + 参_ctn, , #常量4)) -状态条1.置文本 (0, “取acf_ccn-> ” + str) -.如果真 (寻找文本 (str, “error” + #引号 + “:0”, , 假) ≠ -1) - str2 = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/oms/web/pay/getQrCode”, 1, “{” + #引号 + “bizType” + #引号 + “:” + #引号 + “peace” + #引号 + “,” + #引号 + “biz” + #引号 + “:{” + #引号 + “actAlias” + #引号 + “:” + #引号 + “20260120QYOOB” + #引号 + “,” + #引号 + “amount” + #引号 + “:3000,” + #引号 + “roomId” + #引号 + “:9263298},” + #引号 + “ctn” + #引号 + “:” + #引号 + 参_ctn + #引号 + “}”, 参_Cookie + “; ” + “acf_ccn=” + 参_ctn, , #常量4)) - 状态条1.置文本 (0, “开通手册-> ” + str2) - yyjson.清空 () - yyjson.解析 (str2) - 付款30链接 = yyjson.取文本 (“data/qr”) - .如果真 (付款30链接 ≠ “”) - 图片框1.图片 = 文本生成二维码图片 (付款30链接, , , , , 10) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “宝典二维码已生成”) - 状态条1.置文本 (1, “开通宝典,30元支付宝付款码”) - ' 标签反馈.标题 = “开通宝典,30元支付宝付款码” - 返回 () - .如果真结束 - - 窗口_置状态信息 (超级列表框1.现行选中项, 2, str2) - -.如果真结束 - - -.子程序 _开通精英手册30_被选择 - -启动线程 (&查积分记录, , ) -程序_延时 (2000) -启动线程 (&开通30精英, , ) - -.子程序 开通30精英 -.局部变量 局_文本, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_Cookie, 文本型 -.局部变量 ctnEX, 文本型 -.局部变量 str, 文本型 -.局部变量 str2, 文本型 -.局部变量 yyjson, json对象 -.局部变量 付款30链接, 文本型 - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -ctnEX = 超级列表框1.取标题 (超级列表框1.现行选中项, 5) -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_Cookie = 局_F [3] - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/oms/web/peace/item”, 1, “{” + #引号 + “itemId” + #引号 + “:1,” + #引号 + “ctn” + #引号 + “:” + #引号 + ctnEX + #引号 + “}”, 局_Cookie + “; ” + “acf_ccn=” + ctnEX, , #常量4)) -状态条1.置文本 (0, “取acf_ccn-> ” + str) -.如果真 (寻找文本 (str, “error” + #引号 + “:0”, , 假) ≠ -1) - str2 = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/oms/web/pay/getQrCode”, 1, “{” + #引号 + “bizType” + #引号 + “:” + #引号 + “peace” + #引号 + “,” + #引号 + “biz” + #引号 + “:{” + #引号 + “actAlias” + #引号 + “:” + #引号 + “20260120QYOOB” + #引号 + “,” + #引号 + “amount” + #引号 + “:3000,” + #引号 + “roomId” + #引号 + “:9263298},” + #引号 + “ctn” + #引号 + “:” + #引号 + ctnEX + #引号 + “}”, 局_Cookie + “; ” + “acf_ccn=” + ctnEX, , #常量4)) - 状态条1.置文本 (0, “开通手册-> ” + str2) - yyjson.清空 () - yyjson.解析 (str2) - 付款30链接 = yyjson.取文本 (“data/qr”) - ' 输出调试 (“30元支付宝付款码-> ”, 付款30链接) - .如果真 (付款30链接 ≠ “”) - 图片框1.图片 = 文本生成二维码图片 (付款30链接, , , , , 10) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “宝典二维码已生成”) - 状态条1.置文本 (1, “开通宝典,30元支付宝付款码”) - 返回 () - .如果真结束 - - 窗口_置状态信息 (超级列表框1.现行选中项, 2, str2) - -.如果真结束 - - -.子程序 _充值鱼翅_被选择 -.局部变量 返回积分, 文本型 - -返回积分 = 查积分记录 () -.如果真 (返回积分 = “NULL”) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “未开通精英手册”) - 返回 () -.如果真结束 - -.如果真 (到整数 (返回积分) < 10) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “未开通精英手册”) - .如果真 (信息框 (“积分:” + 返回积分 + “,是否充值?”, #信息图标 + #确认钮 + #取消钮, , ) = #取消钮) - 返回 () - .如果真结束 - -.如果真结束 - -窗口_置状态信息 (超级列表框1.现行选中项, 2, “已开通积分:” + 返回积分) -程序_延时 (1000) -启动线程 (&鱼翅充值, , ) - -.子程序 鱼翅充值 -.局部变量 str, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 局_文本, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 鱼刺付款码, 文本型 -.局部变量 鱼刺token, 文本型 -.局部变量 局_bool, 逻辑型 - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “Cookie格式错误”) - 返回 () -.如果真结束 - -' pay_type=1 支付宝支付 pay_type=2 微信支付 - -局_Cookie = 局_F [3] -str = 到文本 (网页_访问_对象 (“https://cz.douyu.com/m/gold/getQrCode”, 1, “pay_type=1&product_id=DYTV_Product_Gold_1&number=” + 删首尾空 (编辑框_充值金额.内容) + “&toname=&source=dy_box”, 局_Cookie, , #常量2)) - -鱼刺付款码 = 编码_usc2到ansi (文本_取出中间文本 (str, “code_url” + #引号 + “:” + #引号, #引号)) -鱼刺token = 文本_取出中间文本 (str, “token” + #引号 + “:” + #引号, #引号) -状态条1.置文本 (0, “鱼翅码-> ” + str) -.如果真 (鱼刺付款码 ≠ “”) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “鱼翅充值码已生成”) - 图片框1.图片 = 文本生成二维码图片 (鱼刺付款码, , , , , 10) - 状态条1.置文本 (1, “鱼翅” + 编辑框_充值金额.内容 + “元,支付宝付款码”) - 程序_延时 (1000) - 检测鱼刺充值状态 (鱼刺token, 超级列表框1.现行选中项, 局_Cookie) - 程序_延时 (2000) - 直接送礼物 (局_Cookie, 超级列表框1.现行选中项) - 程序_延时 (3000) - .计次循环首 (3, ) - 查积分记录 () - .计次循环尾 () - 返回 () -.如果真结束 - -窗口_置状态信息 (超级列表框1.现行选中项, 2, str) - -.子程序 检测鱼刺充值状态 -.参数 参_token, 文本型, 可空 -.参数 参_索引, 整数型 -.参数 参_cook, 文本型 -.局部变量 str, 文本型 -.局部变量 局_余额, 整数型 -.局部变量 局_工作, 逻辑型 -.局部变量 an, 整数型 -.局部变量 msg, 文本型 -.局部变量 yyjson, json对象 - -' 检测充值鱼刺成功 '{"error":0,"data":{"state":2,"order_id":"7682614632081039361001","quantity":10,"nickname":"用户27335596"}} -局_工作 = 真 -.判断循环首 (局_工作 = 真) - _原子递增 (an) - str = 到文本 (网页_访问_对象 (“https://cz.douyu.com/item/gold/account”, , , 参_cook, , #常量2)) - ' '调试输出 (str) - 状态条1.置文本 (0, “[” + 到文本 (an) + “]检测鱼翅充值-> ” + str) - yyjson.清空 () - yyjson.解析 (str) - 局_余额 = yyjson.取整数 (“data/gold”) - ' 调试输出 (“局_余额”, 局_余额) - 窗口_置状态信息 (参_索引, 1, “[” + 到文本 (an) + “]检测鱼翅充值”) - .如果真 (局_余额 > 0) - 窗口_置状态信息 (参_索引, 1, “鱼刺余额:” + 到文本 (局_余额)) - 返回 () - .如果真结束 - - 程序_延时 (2000) -.判断循环尾 () - -.子程序 直接送礼物 -.参数 参_cook, 文本型 -.参数 参_索引, 整数型 -.局部变量 str, 文本型 -.局部变量 局_充值数, 整数型 - -局_充值数 = 到整数 (删首尾空 (编辑框_充值金额.内容)) - -' 正常返回'{"error":0,"msg":"success","data":{"priceType":2,"sb":0,"noble_gold":0,"ry":0,"noble_gold_black":0,"gid":22171,"gx":0,"num":1,"messages":["type@=dgb/rid@=9263298/gfid@=22171/gs@=0/uid@=460469086/bg@=1/nn@=用户470321034/ic@=avatar@Sdefault@S14/eid@=0/eic@=20051/level@=2/dw@=0/gfcnt@=1/hits@=1/bcnt@=1/bst@=6/ct@=0/el@=/cm@=0/bnn@=/bl@=0/brid@=0/hc@=/sahf@=0/fc@=0/bnid@=1/bnl@=1/receive_uid@=335920043/receive_nn@=若若跑的贼快/pfm@=3175/pma@=454872551/mss@=454872569/skinid@=1890/bcst@=1/bsfl@=1/"],"toast":""}} -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/gift/donate/mainsite/v3”, 1, “giftId=23643&giftCount=” + 到文本 (局_充值数) + “&roomId=999&bizExt=%7B%22isMainGift%22%3A1%7D&skinId=2942”, 参_cook, , #常量9)) -状态条1.置文本 (0, “送礼物-> ” + str) -.如果真 (寻找文本 (str, “msg” + #引号 + “:” + #引号 + “success”, , 假) ≠ -1) - 窗口_置状态信息 (参_索引, 1, “送礼物成功”) - 返回 () -.如果真结束 - -窗口_置状态信息 (参_索引, 2, str) - -.子程序 _赠送精英令_被选择 - -启动线程 (&送礼物, , ) - -.子程序 送礼物 -.局部变量 str, 文本型 -.局部变量 局_文本, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_Cookie, 文本型 -.局部变量 局_充值数, 整数型 - -局_充值数 = 到整数 (删首尾空 (编辑框_充值金额.内容)) - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_Cookie = 局_F [3] - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/gift/donate/mainsite/v3”, 1, “giftId=23643&giftCount=” + 到文本 (局_充值数) + “&roomId=9263298&bizExt=%7B%22isMainGift%22%3A1%7D&skinId=2942”, 局_Cookie, , #常量9)) -' 调试输出 (str) -状态条1.置文本 (0, “送礼物-> ” + str) -' 正常返回'{"error":0,"msg":"success","data":{"priceType":2,"sb":0,"noble_gold":0,"ry":0,"noble_gold_black":0,"gid":22171,"gx":0,"num":1,"messages":["type@=dgb/rid@=9263298/gfid@=22171/gs@=0/uid@=460469086/bg@=1/nn@=用户470321034/ic@=avatar@Sdefault@S14/eid@=0/eic@=20051/level@=2/dw@=0/gfcnt@=1/hits@=1/bcnt@=1/bst@=6/ct@=0/el@=/cm@=0/bnn@=/bl@=0/brid@=0/hc@=/sahf@=0/fc@=0/bnid@=1/bnl@=1/receive_uid@=335920043/receive_nn@=若若跑的贼快/pfm@=3175/pma@=454872551/mss@=454872569/skinid@=1890/bcst@=1/bsfl@=1/"],"toast":""}} -.如果真 (寻找文本 (str, “error” + #引号 + “:0”, , 假) ≠ -1) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “送礼物成功”) - 返回 () -.如果真结束 - -窗口_置状态信息 (超级列表框1.现行选中项, 2, str) - -.子程序 _查询手册积分_被选择 - -启动线程 (&查手册积分, , ) - -.子程序 查手册积分 -.局部变量 局_文本, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 ctnEX, 文本型 -.局部变量 str, 文本型 -.局部变量 userid, 文本型 -.局部变量 diff, 文本型 - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -ctnEX = 超级列表框1.取标题 (超级列表框1.现行选中项, 5) - -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “Cookie格式错误”) - 返回 () -.如果真结束 - -userid = 局_F [2] -局_Cookie = 局_F [3] - - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/oms/web/peace/credit/diff”, 1, “{” + #引号 + “userId” + #引号 + “:” + #引号 + userid + #引号 + “,” + #引号 + “ctn” + #引号 + “:” + #引号 + ctnEX + #引号 + “}”, 局_Cookie, , #常量5)) - -' '{"error":0,"msg":"success","data":{"diff":300} -状态条1.置文本 (0, “查积分-> ” + str) -diff = 文本_取出中间文本 (str, “diff” + #引号 + “:”, “}”) -.如果真 (diff ≠ “”) - 窗口_置状态信息 (超级列表框1.现行选中项, 5, “积分:” + diff) - 返回 () -.如果真结束 - -窗口_置状态信息 (超级列表框1.现行选中项, 5, str) - -.子程序 _一键查询积分_被选择 -.局部变量 p, 整数型 - -.计次循环首 (超级列表框1.取表项数 (), p) - .如果真 (超级列表框1.取当前状态图片 (p - 1) = 1) - 启动线程 (&查积分记录_线程, p - 1, ) - 程序_延时 (10) - .如果真结束 - -.计次循环尾 () - -.子程序 查积分记录_线程 -.参数 参_索引E, 整数型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_文本, 文本型 -.局部变量 uid, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 ctnEX, 文本型 -.局部变量 str, 文本型 -.局部变量 balance, 文本型 - -全临界.进入 () -局_文本 = 超级列表框1.取标题 (参_索引E, 1) -ctnEX = 超级列表框1.取标题 (参_索引E, 5) -全临界.退出 () - -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (参_索引E, 2, “Cookie格式错误”) - 返回 () -.如果真结束 - -uid = 局_F [2] -局_Cookie = 局_F [3] - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/oms/web/peace/credit/balance”, 1, “{” + #引号 + “uid” + #引号 + “:” + #引号 + uid + #引号 + “,” + #引号 + “ctn” + #引号 + “:” + #引号 + ctnEX + #引号 + “}”, 局_Cookie, , #常量6)) -balance = 文本_取出中间文本 (str, “balance” + #引号 + “:”, “,”) -状态条1.置文本 (0, “积分记录-> ” + str) - -.如果 (balance ≠ “”) - 窗口_置状态信息 (参_索引E, 2, “记录积分:” + balance) -.否则 - 窗口_置状态信息 (参_索引E, 2, “NULL”) -.如果结束 - -返回 () - -.子程序 查积分记录, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_文本, 文本型 -.局部变量 uid, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 ctnEX, 文本型 -.局部变量 str, 文本型 -.局部变量 balance, 文本型 - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -ctnEX = 超级列表框1.取标题 (超级列表框1.现行选中项, 5) - -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “Cookie格式错误”) - 返回 (“NULL”) -.如果真结束 - -uid = 局_F [2] -局_Cookie = 局_F [3] - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/oms/web/peace/credit/balance”, 1, “{” + #引号 + “uid” + #引号 + “:” + #引号 + uid + #引号 + “,” + #引号 + “ctn” + #引号 + “:” + #引号 + ctnEX + #引号 + “}”, 局_Cookie, , #常量6)) -balance = 文本_取出中间文本 (str, “balance” + #引号 + “:”, “,”) -状态条1.置文本 (0, “积分记录-> ” + str) - -.如果真 (balance ≠ “”) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “记录积分:” + balance) - 返回 (balance) -.如果真结束 - -窗口_置状态信息 (超级列表框1.现行选中项, 2, “NULL”) -返回 (“NULL”) - -.子程序 _兑换商品_被选择 - -启动线程 (&商品兑换, , ) - -.子程序 Getctn, 文本型 -.局部变量 局_文本, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_CCK, 文本型 -.局部变量 str, 文本型 -.局部变量 返回CK, 文本型 -.局部变量 ctn1, 文本型 -.局部变量 ctn2, 文本型 -.局部变量 局_CK, 文本型 -.局部变量 str2, 文本型 - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 返回 (“”) -.如果真结束 - -局_CCK = 局_F [3] - -str = 到文本 (网页_访问_对象 (“https://www.douyu.com/curl/csrfApi/getCsrfCookie?”, , , 局_CCK, 返回CK, #常量1)) -ctn1 = 文本_取出中间文本 (返回CK, “acf_ccn=”, “;”) -.如果真 (ctn1 ≠ “”) - str2 = 到文本 (网页_访问_对象 (“https://www.douyu.com/wgapi/livenc/asubscribe/userSubStatus”, 1, “subscribe=cmn&ctn=” + ctn1, 返回CK, 局_CK, #常量1)) - ' 调试输出 (局_CK) - .如果真 (寻找文本 (str, “error” + #引号 + “:0”, , 假) ≠ -1) - ctn2 = 文本_取出中间文本 (局_CK, “acf_ccn=”, “;”) - 返回 (ctn2) - .如果真结束 - - 返回 (“”) - -.如果真结束 - -返回 (“”) - -.子程序 Getcsrf_token, 文本型 -.参数 参_CK, 文本型 -.局部变量 局_文本, 文本型 -.局部变量 局_CCK, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 str, 文本型 -.局部变量 返回CK, 文本型 -.局部变量 csrf_token, 文本型 - -str = 到文本 (网页_访问_对象 (“https://www.douyu.com/japi/carnival/nc/common/generateCsrf”, 1, , 参_CK, 返回CK, #常量10)) -csrf_token = 文本_取出中间文本 (返回CK, “cvl_csrf_token=”, “;”) -' '调试输出 (返回CK, , , csrf_token) -返回 (csrf_token) - -.子程序 商品兑换 -.局部变量 局_文本, 文本型 -.局部变量 ctnEX, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_Cookie, 文本型 -.局部变量 str, 文本型 -.局部变量 局_xy, 文本型 -.局部变量 商品表, 文本型 -.局部变量 商品组, 文本型, , "0" -.局部变量 要兑换的商品名称, 文本型 -.局部变量 要兑换的商品价格, 文本型 -.局部变量 要兑换的商品ID, 文本型 -.局部变量 roleName, 文本型 -.局部变量 str2, 文本型 -.局部变量 局_bin, 字节集 -.局部变量 生成者, 文本型 -.局部变量 优化价格, 文本型 -.局部变量 areaName, 文本型 -.局部变量 platName, 文本型 -.局部变量 COOK, 文本型 -.局部变量 局_F2, 文本型, , "0" -.局部变量 局_文本EX, 文本型 -.局部变量 局_用户名, 文本型 -.局部变量 csrf_token, 文本型 -.局部变量 body, 文本型 -.局部变量 randstr, 文本型 -.局部变量 sendxy, 文本型 -.局部变量 yyjson, json对象 - -' 局_文本EX = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -' 局_F2 = 分割文本 (局_文本EX, “----”, ) -.' 如果真 (取数组成员数 (局_F2) < 3) - ' 返回 () -.如果真结束 - -' 局_用户名 = 局_F2 [1] - -商品表 = 组合框1.取项目文本 (组合框1.现行选中项) -商品组 = 分割文本 (商品表, “一”, ) -.如果真 (取数组成员数 (商品组) < 3) - 状态条1.置文本 (0, “商品格式错误x”) - 返回 () -.如果真结束 - -要兑换的商品名称 = 商品组 [1] -要兑换的商品价格 = 商品组 [2] -要兑换的商品ID = 商品组 [3] - -状态条1.置文本 (0, “正在兑换商品-> ” + 要兑换的商品ID) - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (超级列表框1.现行选中项, 4, “Cookie格式错误”) - 状态条1.置文本 (0, “Cookie格式错误x ”) - 返回 () -.如果真结束 - -局_用户名 = 局_F [1] -局_Cookie = 局_F [3] - -ctnEX = 文本_取出中间文本 (局_Cookie, “acf_ccn=”, “;”) -COOK = 局_Cookie + “; acf_ccn=” + ctnEX -.如果真 (寻找文本 (COOK, “;;”, , 假) ≠ -1) - COOK = 子文本替换 (COOK, “;;”, “;”, , , 真) -.如果真结束 - -csrf_token = Getcsrf_token (局_Cookie) - -COOK = 网页_Cookie合并更新 (COOK, “cvl_csrf_token=” + csrf_token) - -置随机数种子 () -randstr = 文本_取随机字符 (16, 位或 (1, 2, 4)) -sendxy = 子文本替换 (#常量12, “[randstr]”, randstr, , , 真) -body = 文本_替换 (#常量11, , , , “[randstr]”, randstr, “[manualID]”, “G4KA4Qnz4LDp7”, “[商品ID]”, 要兑换的商品ID, “[token]”, csrf_token) -调试输出 (“body:--”, body) - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/wgapi/ordnc/activity/peace/exchange”, 1, body, COOK, , sendxy, 局_xy)) -' 调试输出 (“兑换商品-> ” + str) -状态条1.置文本 (0, “兑换商品-> ” + str) -.如果真 (寻找文本 (str, “error” + #引号 + “:0”, , 假) ≠ -1) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “兑换成功:” + 要兑换的商品名称) - .计次循环首 (3, ) - str2 = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/v2/tencent/bindInfo?actAlias=20260120QYOOB”, , , 局_Cookie, , #常量3)) - .如果真 (str2 ≠ “”) - 跳出循环 () - .如果真结束 - - .计次循环尾 () - - - yyjson.清空 () - yyjson.解析 (str2) - roleName = yyjson.取文本 (“data/gameRole/roleName”) - .如果 (roleName ≠ “”) - 全线程临界.进入 () - 优化价格 = 取文本左边 (要兑换的商品价格, 取文本长度 (要兑换的商品价格) - 1) - 保存日志2 (时间_到文本 (取现行时间 (), 1) + “ ” + 局_用户名 + “----” + roleName + “----” + 要兑换的商品名称 + “----” + 优化价格) - 局_bin = 文转图片P (要兑换的商品名称 + “ ” + #换行符 + 时间_格式化 (取现行时间 (), “yyyy年MM月dd日”, “ hh:mm:ss”, 真) + #换行符 + “兑换账号:” + roleName + “(” + 局_用户名 + “)”) - 全线程临界.退出 () - 剪辑板_置图片 (局_bin) - 提示框 (“兑换成功,图片已复制”, , , , 1000) - - .否则 - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “兑换成功,获取昵称失败”) - - .如果结束 - - 返回 () - -.如果真结束 - - -窗口_置状态信息 (超级列表框1.现行选中项, 2, “兑换失败”) - -.子程序 查积分记录EX, 文本型 -.参数 参_uid, 文本型 -.参数 参_CK, 文本型 -.参数 参_ctnEX, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_文本, 文本型 -.局部变量 str, 文本型 -.局部变量 balance, 文本型 -.局部变量 yyjson, json对象 - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/oms/web/peace/credit/balance”, 1, “{” + #引号 + “uid” + #引号 + “:” + #引号 + 参_uid + #引号 + “,” + #引号 + “ctn” + #引号 + “:” + #引号 + 参_ctnEX + #引号 + “}”, 参_CK, , #常量6)) -balance = 文本_取出中间文本 (str, “balance” + #引号 + “:”, “,”) -状态条1.置文本 (0, “积分记录-> ” + str) -返回 (balance) - -.子程序 _图片框1_被双击, 逻辑型 -.参数 横向位置, 整数型 -.参数 纵向位置, 整数型 -.参数 功能键状态, 整数型 - -.如果真 (图片框1.图片 = { }) - 提示框 (“请先生成后,再复制二维码”, , , , 1000) - 返回 () -.如果真结束 - -剪辑板_置图片 (图片框1.图片) -' 剪辑板_置图片 (图片_后台截图 (图片框4.取窗口句柄 ())) -提示框 (“二维码已复制”, , , , 1000) - -.子程序 _超级列表框1_被双击, 逻辑型 -.参数 横向位置, 整数型 -.参数 纵向位置, 整数型 -.参数 功能键状态, 整数型 - -启动线程 (&子程序标签更新, , ) - -.子程序 子程序标签更新 -.局部变量 局_文本, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_uid, 文本型 -.局部变量 nick, 文本型 -.局部变量 str, 文本型 -.局部变量 roleName, 文本型 -.局部变量 余额, 文本型 -.局部变量 areaName, 文本型 -.局部变量 platName, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 局_ctn, 文本型 -.局部变量 yyjson, json对象 -.局部变量 manualScore, 文本型 - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -局_ctn = 超级列表框1.取标题 (超级列表框1.现行选中项, 5) -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 状态条1.置文本 (0, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_uid = 局_F [2] -局_Cookie = 局_F [3] -' 'https://www.douyu.com/japi/carnivalApi/tencent/bindInfo?actAlias=20260120QYOOB -' 这个回头调整 str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/v2/tencent/bindInfo?actAlias=cjm”, , , 局_Cookie, , #常量3)) -' https://www.douyu.com/wgapi/ordnc/live/memberthird/tencent/bindInfo?actAlias=20260226ZMGDG - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/tencent/bindInfo?actAlias=20260120QYOOB”, , , 局_Cookie, , #常量3)) -' 调试输出 (str) -状态条1.置文本 (0, “是否绑定-> ” + str) -' {"error":0,"msg":"success","data":{"bindAccount":1,"bindRole":1,"bindAct":1,"needBindRole":null,"txAct":{"txActId":2811,"gameId":"cjm","gameName":"和平精英","bindType":1},"gameAccount":{"bindType":2,"type":"","faceuri":"https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTI4cIOxb4f7vpSkqYCIIvY1EJTgkhS0ZhVzzJSl2LzDpUzVBJKiaDjvuzpdS6cadAvA6bnrYwZ7jlQ/132","nick":"zicoo"},"gameRole":{"roleName":"白菜被拱了呀","areaName":"微信","platName":"安卓(android)","partitionName":""},"i sGranted":null,"gameAuthScene":null,"canChangeRole":0,"changeRoleWaitTime":2490528},"redirectUrl":null} -yyjson.清空 () -yyjson.解析 (str) - -roleName = yyjson.取文本 (“data/gameRole/roleName”) -' 文本_取出中间文本 (str, “roleName” + #引号 + “:” + #引号, #引号) -nick = yyjson.取文本 (“data/gameAccount/nick”) -' 文本_取出中间文本 (str, “nick” + #引号 + “:” + #引号, #引号) -areaName = yyjson.取文本 (“data/gameRole/areaName”) -' 文本_取出中间文本 (str, “areaName” + #引号 + “:” + #引号, #引号) -platName = yyjson.取文本 (“data/gameRole/platName”) -' 文本_取出中间文本 (str, “platName” + #引号 + “:” + #引号, #引号) -余额 = 查积分记录EX (局_uid, 局_Cookie, 局_ctn) - -标签_昵称.标题 = “账号:” + 局_F [1] + “<->” + “余额:” + 余额 -标签_状态.标题 = “昵称:” + nick + #换行符 + “游戏名称:” + roleName + #换行符 + “平台:” + areaName + #换行符 + “设备:” + platName -超级列表框1.置标题 (超级列表框1.现行选中项, 2, roleName) - -.子程序 _标签_状态_被双击, 逻辑型 -.参数 横向位置, 整数型 -.参数 纵向位置, 整数型 -.参数 功能键状态, 整数型 - -剪辑板_置图片 (快照 (标签_状态.取窗口句柄 (), , )) -提示框 (“图片已复制”, , , , 1000) - -.子程序 _窗口1_可否被关闭, 逻辑型 - -.如果 (信息框 (“确定要退出程序吗?”, #信息图标 + #确认钮 + #取消钮, , ) = #确认钮) - 返回 (真) -.否则 - 返回 (假) -.如果结束 - - -.子程序 _窗口1_将被销毁 - -配置_保存_易语言组件 (窗口1) -Gdip结束 () -数据写出列表 () - -.子程序 _按钮_结算_被单击 - -启动线程 (&子程序结算, , ) - -.子程序 子程序结算 -.局部变量 str, 文本型 -.局部变量 局_1, 文本型, , "0" -.局部变量 局_F, 文本型, , "0" -.局部变量 N, 整数型 -.局部变量 局_NUM, 整数型 -.局部变量 局_日志路径, 文本型 -.局部变量 局_标识, 文本型, , "0" -.局部变量 局_文本1, 文本型 -.局部变量 局_文本2, 文本型 -.局部变量 局_返回余额, 整数型 - -局_日志路径 = 取运行目录 () + “\” + 时间_格式化 (取现行时间 (), “MM.dd-”) + “兑换日志.log” -str = 编码_Utf8到Ansi (读入文件 (局_日志路径)) -.如果真 (str = “”) - 提示框 (“生成日志后,再结算金额...”, , , , 1000) - 返回 () -.如果真结束 - -文本_取中间_批量 (str, “---------------------------------------------已结算----以上合计金额:”, #换行符, 局_标识) -.如果真 (取数组成员数 (局_标识) < 1) - ' 提示框 (“生成日志后,再结算金额”, , , , 2000) - 局_F = 分割文本 (str, #换行符, ) - .计次循环首 (取数组成员数 (局_F), N) - 局_返回余额 = 子程序处理余额 (局_F [N]) - _原子运算 (局_NUM, 局_返回余额) - 系统_处理事件 () - .计次循环尾 () - 保存日志2 (#换行符 + #换行符 + “---------------------------------------------已结算----以上合计金额:” + 到文本 (局_NUM) + #换行符 + #换行符) - 提示框 (“结算完成:” + 到文本 (局_NUM), , , , 2000) - 返回 () -.如果真结束 - - -.如果真 (局_标识 [取数组成员数 (局_标识)] ≠ “”) - 局_文本1 = “---------------------------------------------已结算----以上合计金额:” + 局_标识 [取数组成员数 (局_标识)] - 局_1 = 分割文本 (str, 局_文本1, ) - 局_文本2 = 局_1 [取数组成员数 (局_1)] - .如果真 (局_文本2 ≠ “”) - 局_F = 分割文本 (局_文本2, #换行符, ) - .计次循环首 (取数组成员数 (局_F), N) - 局_返回余额 = 子程序处理余额 (局_F [N]) - _原子运算 (局_NUM, 局_返回余额) - 系统_处理事件 () - .计次循环尾 () - .如果真 (局_NUM ≤ 0) - 提示框 (“未达到结算条件!”, , , , 2000) - 返回 () - .如果真结束 - - 保存日志2 (#换行符 + #换行符 + “---------------------------------------------已结算----以上合计金额:” + 到文本 (局_NUM) + #换行符 + #换行符) - 清除数组 (局_1) - 清除数组 (局_F) - 提示框 (“结算完成:” + 到文本 (局_NUM), , , , 2000) - 返回 () - .如果真结束 - - 提示框 (“未达到结算条件!”, , , , 2000) - -.如果真结束 - - -.子程序 子程序处理余额, 整数型 -.参数 参_数据, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 N, 整数型 - -局_F = 分割文本 (参_数据, “----”, ) -.如果真 (取数组成员数 (局_F) = 4) - 返回 (到整数 (局_F [4])) -.如果真结束 - -返回 (0) - -.子程序 _按钮_统计_被单击 -.局部变量 str, 文本型 -.局部变量 局_日志路径, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 P, 整数型 -.局部变量 局_返回余额, 整数型 -.局部变量 局_NUM, 整数型 - -局_日志路径 = 取运行目录 () + “\” + 时间_格式化 (取现行时间 (), “MM.dd-”) + “兑换日志.log” -str = 编码_Utf8到Ansi (读入文件 (局_日志路径)) -局_F = 分割文本 (str, #换行符, ) -.计次循环首 (取数组成员数 (局_F), P) - 局_返回余额 = 子程序处理余额 (局_F [P]) - _原子运算 (局_NUM, 局_返回余额) - 系统_处理事件 () -.计次循环尾 () -保存日志2 (#换行符 + #换行符 + “*************************************************今日统计总金额:” + 到文本 (局_NUM) + #换行符 + #换行符) -信息框 (时间_格式化 (取现行时间 (), “MM.dd-”) + “统计总金额:” + 到文本 (局_NUM), 0, , ) - - -.子程序 _读取Cookie_被选择 -.局部变量 局_保存目录, 文本型 -.局部变量 局_文本数据, 文本型 -.局部变量 局_文本数组, 文本型, , "0" -.局部变量 局_索引, 整数型 -.局部变量 P, 整数型 -.局部变量 N, 整数型 -.局部变量 局_3, 文本型, , "0" - -局_保存目录 = 取运行目录 () + “\斗鱼CK\” + 时间_格式化 (取现行时间 (), “MM.dd-”) + “斗鱼CK.txt” -.如果真 (文件是否存在 (局_保存目录) = 假) - 提示框 (“Cookie文件不存在!” + #换行符 + 局_保存目录, , , , 2000) - 返回 () -.如果真结束 - - -局_文本数据 = 到文本 (读入文件 (局_保存目录)) -局_文本数组 = 分割文本 (局_文本数据, #换行符, ) -.计次循环首 (取数组成员数 (局_文本数组), P) - 判断重复列表 (局_文本数组 [P]) - 系统_处理事件 () -.计次循环尾 () -.计次循环首 (超级列表框1.取表项数 (), N) - 系统_处理事件 () - 超级列表框1.置状态图片 (N - 1, 1) - 超级列表框1.置标题 (N - 1, 0, 到文本 (N)) -.计次循环尾 () - -.子程序 判断重复列表 -.参数 参_内容, 文本型 -.局部变量 局_文本, 文本型 -.局部变量 局_用户, 文本型 -.局部变量 _索引, 整数型 -.局部变量 局_索引2, 整数型 -.局部变量 P, 整数型 - -_索引 = 超级列表框1.查找表项 (参_内容, , , 1) -.如果 (_索引 = -1) - 局_索引2 = 超级列表框1.插入表项 (, , , , , ) - 超级列表框1.置标题 (局_索引2, 0, 到文本 (局_索引2 + 1)) - 超级列表框1.置标题 (局_索引2, 1, 参_内容) - 超级列表框1.置状态图片 (局_索引2, 1) - -.否则 - 超级列表框1.置标题 (_索引, 1, 参_内容) -.如果结束 - - -.子程序 _同步删除Cookie_被选择 -.局部变量 局_保存目录, 文本型 -.局部变量 局_保存文本, 鱼刺类_输出文本 -.局部变量 i, 整数型 -.局部变量 P, 整数型 - -局_保存目录 = 取运行目录 () + “\斗鱼CK\” + 时间_格式化 (取现行时间 (), “MM.dd-”) + “斗鱼CK.txt” -超级列表框1.删除表项 (超级列表框1.现行选中项) -删除文件 (局_保存目录) -程序_延时 (500) -局_保存目录 = 取运行目录 () + “\斗鱼CK\” -.计次循环首 (超级列表框1.取表项数 (), i) - 系统_处理事件 () - 局_保存文本.写文本行 (超级列表框1.取标题 (i - 1, 1), 时间_格式化 (取现行时间 (), “MM.dd-”) + “斗鱼CK”, 局_保存目录, “.txt”) -.计次循环尾 () -.计次循环首 (超级列表框1.取表项数 (), P) - 系统_处理事件 () - 超级列表框1.置状态图片 (P - 1, 1) - 超级列表框1.置标题 (P - 1, 0, 到文本 (P)) -.计次循环尾 () - -提示框 (“同步完成”, , , , 1000) - -.子程序 保存日志 -.参数 参_str, 文本型 -.局部变量 filename, 文本型 -.局部变量 保存到文件, 鱼刺类_输出文本 - -filename = 时间_格式化 (取现行时间 (), “MM.dd-”) + “流程日志” -保存到文件.写文本行 (参_str, filename, 取运行目录 () + “\”, “.log”) - -.子程序 保存日志2 -.参数 参_str, 文本型 -.局部变量 filename, 文本型 -.局部变量 保存到文件, 鱼刺类_输出文本 - -filename = 时间_格式化 (取现行时间 (), “MM.dd-”) + “兑换日志” -保存到文件.写文本行 (参_str, filename, 取运行目录 () + “\”, “.log”) -' 保存到文件.关闭所有文件占用 () - -.子程序 数据写入列表, , , APP -.局部变量 文件号, 整数型 -.局部变量 文件名, 文本型 -.局部变量 状态数组, 文本型, , "0" -.局部变量 文本数组, 文本型, , "0" -.局部变量 M, 整数型 -.局部变量 N, 整数型 -.局部变量 局_状态图片, 整数型 - -文件名 = 全目录临时 + “\临时ck.txt” -文件号 = 打开文件 (文件名, , ) -移到文件首 (文件号) -处理事件 () -.判断循环首 (取反 (是否在文件尾 (文件号, 真))) - 重定义数组 (状态数组, 假, 0) - 重定义数组 (文本数组, 假, 0) - 状态数组 = 分割文本 (读入一行 (文件号), “$”, ) - .如果真 (取数组成员数 (状态数组) ≥ 2) - .如果 (状态数组 [1] = “x”) - 局_状态图片 = 1 - .否则 - 局_状态图片 = 0 - .如果结束 - 文本数组 = 分割文本 (状态数组 [2], “|||”, ) - M = 超级列表框1.插入表项 (, , , , , ) - - 超级列表框1.置状态图片 (M, 局_状态图片) - .计次循环首 (取数组成员数 (文本数组), N) - 系统_处理事件 () - 超级列表框1.置标题 (M, N - 1, 文本数组 [N]) - .如果真 (N = 20) ' 填充满一页就手动重画 - 超级列表框1.禁止重画 () - .如果真结束 - .如果真 (N % 100 = 0) ' 每100次插入 换一次姿势 ``233333 - 超级列表框1.允许重画 () - 超级列表框1.发送信息 (277, 7, 0) ' 显示最后一行 - 超级列表框1.禁止重画 () - .如果真结束 - - .计次循环尾 () - - - - .如果真结束 - -.判断循环尾 () -关闭文件 (文件号) -超级列表框1.允许重画 () ' 恢复自动重画 -超级列表框1.发送信息 (277, 7, 0) ' 显示最后一行 - -.子程序 数据写出列表, , , APP -.局部变量 文件名, 文本型 -.局部变量 读入账号, 文本型 -.局部变量 n, 整数型 -.局部变量 临时文件名, 文本型 -.局部变量 文件号, 整数型 -.局部变量 文本, 文本型 -.局部变量 空, 字节集 -.局部变量 局_状态图片, 文本型 - -临时文件名 = 全目录临时 + “\临时ck.txt” -文件号 = 打开文件 (临时文件名, 4, ) -_处理事件 () -文本 = “” - -.计次循环首 (超级列表框1.取表项数 (), n) - 系统_处理事件 () - .判断开始 (超级列表框1.取当前状态图片 (n - 1) = 1) - 局_状态图片 = “x” - - .默认 - 局_状态图片 = “y” - .判断结束 - - 文本 = 局_状态图片 + “$” + 超级列表框1.取标题 (n - 1, 0) + “|||” + 超级列表框1.取标题 (n - 1, 1) + “|||” + 超级列表框1.取标题 (n - 1, 2) + “|||” + 超级列表框1.取标题 (n - 1, 3) + “|||” + 超级列表框1.取标题 (n - 1, 4) + “|||” + 超级列表框1.取标题 (n - 1, 5) + “|||” + 超级列表框1.取标题 (n - 1, 6) - - 写文本行 (文件号, 文本) -.计次循环尾 () -关闭文件 (文件号) - -.子程序 _标签_昵称_被双击, 逻辑型, , https://livelink.qq.com/act/a20200527midgroupage/pc/?sig=0d29d14f3e9bdb05f7f091340952054f&faceUrl=https%3A%2F%2Fapic.douyucdn.cn%2Fupload%2Favatar%2Fdefault%2F15_middle.jpg&code=wW6EhNWpLEVNHKEMfB9vaEWKPdowIikRqFJI0IKm%2BcxGa%2B8OEPhyF%2BZ58W80CrGigCGtLddIofBcnRkylmccKw%3D%3D&redirectUrl=null&t=1661433534&livePlatId=douyu&nickName=%E7%94%A8%E6%88%B702435853&actId=2811&gameIdList=cjm -.参数 横向位置, 整数型 -.参数 纵向位置, 整数型 -.参数 功能键状态, 整数型 -.局部变量 str, 文本型, , , 昵称:null <-> 余额:null - -str = 删首尾空 (文本_取出中间文本 (标签_昵称.标题, “账号:”, “<->”)) -置剪辑板文本 (str) -提示框 (str + “ 已复制”, , , , 1000) - -.子程序 _按钮_关闭_被单击, , , 测试 - -_扫码框.可视 = 假 -工作中 = 假 -关闭线程句柄 (集句柄) -强制结束线程 (集句柄) - -.子程序 _扫码登录_被选择 - -' 载入 (窗口_扫码, , 真) -_扫码框.可视 = 真 -标签显示.可视 = 假 -按钮_刷新.可视 = 假 -按钮_刷新.禁止 = 真 -启动线程 (&getscanEX, , 集句柄) - -.子程序 getscanEX, 逻辑型, , 获取扫码 -.局部变量 str, 文本型 -.局部变量 yyjson, json对象 -.局部变量 surl, 文本型 -.局部变量 code, 文本型 -.局部变量 bool, 逻辑型 -.局部变量 局_Code, 文本型 -.局部变量 局_msg, 文本型 -.局部变量 局_LoginUrl, 文本型 -.局部变量 CK, 文本型 - -图片框2.图片 = { } -网页_清除Cookie (“passport.douyu.com”) -标签_反馈.标题 = “正在二维码...” -网页_访问_对象 (“https://passport.douyu.com/index/login?passport_reg_callback=PASSPORT_REG_SUCCESS_CALLBACK&passport_login_callback=PASSPORT_LOGIN_SUCCESS_CALLBACK&passport_close_callback=PASSPORT_CLOSE_CALLBACK&passport_dp_callback=PASSPORT_DP_CALLBACK&type=login&client_id=1&state=https%3A%2F%2Fwww.douyu.com%2F&source=click_topnavi_login”, , , “dy_did=05444ffb59d181b4d194b59900011601; acf_did=05444ffb59d181b4d194b59900011601; Hm_lpvt_e99aee90ec1b2106afe7ec3b199020a7=” + 到文本 (时间_取现行时间戳1 (假)), , #常量8) -程序_延时 (1000) -str = 编码_usc2到ansi (到文本 (网页_访问_对象 (“https://passport.douyu.com/scan/generateCode”, 1, “client_id=1&isMultiAccount=0”, “dy_did=05444ffb59d181b4d194b59900011601; acf_did=05444ffb59d181b4d194b59900011601; Hm_lpvt_e99aee90ec1b2106afe7ec3b199020a7=” + 到文本 (时间_取现行时间戳1 (假)), , #扫码XY1))) - -' “dy_did=05444ffb59d181b4d194b59900011601; acf_did=05444ffb59d181b4d194b59900011601; Hm_lpvt_e99aee90ec1b2106afe7ec3b199020a7=” + 到文本 (时间_取现行时间戳1 (假)) - -' 调试输出 (str) -yyjson.清空 () -yyjson.解析 (str) -surl = yyjson.取文本 (“data/url”) -局_Code = yyjson.取文本 (“data/code”) -.如果真 (surl = “” 或 局_Code = “”) - 标签_反馈.标题 = “请关闭后重新生成二维码!” - 返回 (假) -.如果真结束 - -图片框2.图片 = 文本生成二维码图片 (surl, , , , , 20) -标签_反馈.标题 = “二维码已生成,请在手机上确认!” - -工作中 = 真 -.判断循环首 (工作中 = 真) - bool = scanauthEX (局_Code, 局_msg, 局_LoginUrl) - .如果真 (bool = 真) - 跳出循环 () - .如果真结束 - - .如果真 (寻找文本 (局_msg, “code不存在或者是已经过期”, , 假) ≠ -1) - 关闭线程句柄 (集句柄) - 强制结束线程 (集句柄) - 标签显示.可视 = 真 - 按钮_刷新.可视 = 真 - 按钮_刷新.禁止 = 假 - 返回 (假) - .如果真结束 - - 程序_延时 (1000) - 系统_处理事件 () -.判断循环尾 () -Login_douEX (局_LoginUrl) -返回 (真) - -.子程序 scanauthEX, 逻辑型, , 检测是否扫码 -.参数 参_code, 文本型 -.参数 返回msg, 文本型, 参考 -.参数 返回登录url, 文本型, 参考 -.局部变量 str, 文本型 -.局部变量 yyjson, json对象 -.局部变量 局_msg, 文本型 -.局部变量 局surl, 文本型 - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://passport.douyu.com/japi/scan/auth?time=” + 时间_取现行时间戳 () + “&code=” + 参_code, , , , , #扫码XY1)) -' 调试输出 (“参_code---”, 参_code) -' 调试输出 (str) -yyjson.清空 () -yyjson.解析 (str) -返回msg = yyjson.取文本 (“msg”) -返回登录url = yyjson.取文本 (“data/url”) -标签_反馈.标题 = “>>>>” + 返回msg -.如果真 (返回登录url ≠ “”) - 标签_反馈.标题 = “扫码成功,正在登录...” - 返回 (真) -.如果真结束 - -返回 (假) - -.子程序 Login_douEX, , , 登录斗鱼 -.参数 参_url, 文本型 -.局部变量 str, 文本型 -.局部变量 局_索引, 整数型 -.局部变量 局_COOK, 文本型 -.局部变量 acf_uid, 文本型 -.局部变量 acf_nickname, 文本型 -.局部变量 解析CK, 类_Cookie - -str = 编码_usc2到ansi (到文本 (网页_访问_对象 (参_url + “&callback=appClient_json_callback&_=” + 时间_取现行时间戳 (), , , , 局_COOK, #扫码登录))) -' 调试输出 (str) -' 调试输出 (“局_COOK---”, 局_COOK) -.如果真 (局_COOK ≠ “”) - 标签_反馈.标题 = “>>>扫码登录成功!” - acf_uid = 网页_取单条Cookie (局_COOK, “acf_uid”, 真) - - acf_nickname = 编码_URL解码 (网页_取单条Cookie (局_COOK, “acf_nickname”, 真), 真) - 局_索引 = 超级列表框1.插入表项 (, , , , , ) - 超级列表框1.置标题 (局_索引, 0, 到文本 (局_索引 + 1)) - 超级列表框1.置标题 (局_索引, 1, acf_nickname + “----” + acf_uid + “----” + 局_COOK) - 超级列表框1.置状态图片 (局_索引, 1) - 超级列表框1.保证显示 (局_索引) - 工作中 = 假 - _扫码框.可视 = 假 - -.如果真结束 - - -.子程序 _按钮_刷新_被单击 - -标签显示.可视 = 假 -按钮_刷新.可视 = 假 -按钮_刷新.禁止 = 真 -启动线程 (&getscanEX, , 集句柄) - -.子程序 _图片框2_被双击, 逻辑型 -.参数 横向位置, 整数型 -.参数 纵向位置, 整数型 -.参数 功能键状态, 整数型 - -剪辑板_置图片 (图片框2.图片) -提示框 (“图片已复制”, , , , 1000) - -.子程序 __扫码框_鼠标左键被按下, 逻辑型 -.参数 横向位置, 整数型 -.参数 纵向位置, 整数型 -.参数 功能键状态, 整数型 - -窗口1.发送信息 (161, 2, 0) - -.子程序 _粘贴Cookie_被选择 -.局部变量 文本数组, 文本型, , "0" -.局部变量 计次1, 整数型 -.局部变量 计次2, 整数型 -.局部变量 临时数组, 文本型, , "0" -.局部变量 索引, 整数型 -.局部变量 i, 文本型 -.局部变量 总数数组, 文本型, , "0" -.局部变量 内容, 文本型 -.局部变量 X, 整数型 -.局部变量 状态数组, 文本型, , "0" -.局部变量 N, 整数型 -.局部变量 M, 整数型 -.局部变量 判断数据, 文本型 - -' 下面的是粘贴根据“----“判断是否是一条或者两条数据 -i = 取剪辑板文本 () -.如果真 (i = “”) - 返回 () -.如果真结束 - -文本数组 = 分割文本 (i, #换行符, ) -.计次循环首 (取数组成员数 (文本数组), X) - .如果真 (文本数组 [X] ≠ “”) - M = 超级列表框1.插入表项 (, , , , , ) - 超级列表框1.置状态图片 (M, 1) - 超级列表框1.置标题 (M, 0, 到文本 (M + 1)) - 超级列表框1.置标题 (M, 1, 文本数组 [X]) - .如果真结束 - - 系统_处理事件 () -.计次循环尾 () -超级列表框1.允许重画 () ' 恢复自动重画 -超级列表框1.发送信息 (277, 7, 0) ' 显示最后一行 - -清除数组 (文本数组) -返回 () - -.子程序 _搜索游戏名_被选择 -.局部变量 索引EX, 整数型 -.局部变量 str, 文本型 - -输入框 (“查找包含游戏名的字符”, “查找游戏名”, , str, , ) -.如果真 (str = “”) - 返回 () -.如果真结束 - -索引EX = 超级列表框1.查找表项 (str, , 假, 2) -.如果真 (索引EX ≠ -1) - 超级列表框1.保证显示 (索引EX) - 超级列表框1.选择表项 (索引EX) -.如果真结束 - -返回 () - -.子程序 _搜索状态_被选择 -.局部变量 索引EX, 整数型 -.局部变量 str, 文本型 - -输入框 (“查找包含状态的字符”, “查找状态”, , str, , ) -.如果真 (str = “”) - 返回 () -.如果真结束 - -索引EX = 超级列表框1.查找表项 (str, , 假, 4) -.如果真 (索引EX ≠ -1) - 超级列表框1.保证显示 (索引EX) - 超级列表框1.选择表项 (索引EX) -.如果真结束 - -返回 () - - -.子程序 子程序检测账号EX -.参数 参_索引, 整数型 -.局部变量 局_文本, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_CCK, 文本型 -.局部变量 str, 文本型 -.局部变量 返回CK, 文本型 - -全检车临界.进入 () -局_文本 = 超级列表框1.取标题 (参_索引, 1) -全检车临界.退出 () - -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (参_索引, 2, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_CCK = 局_F [3] -str = 到文本 (网页_访问_对象 (“https://www.douyu.com/curl/csrfApi/getCsrfCookie?”, , , 局_CCK, , #常量1)) -' 调试输出 (str) -状态条1.置文本 (0, “生成1-> ” + 编码_usc2到ansi (str)) -.判断开始 (寻找文本 (str, “-99”, , 假) ≠ -1) - 窗口_置状态信息 (参_索引, 1, “账号未登录”) - 返回 () - -.判断 (寻找文本 (str, “无效”, , 假) ≠ -1) - 窗口_置状态信息 (参_索引, 1, “账号无效”) - 返回 () - -.默认 - 窗口_置状态信息 (参_索引, 1, “账号正常”) -.判断结束 - -返回 () - -.子程序 _一键检测账号_被选择 -.局部变量 p, 整数型 - -.计次循环首 (超级列表框1.取表项数 (), p) - .如果真 (超级列表框1.取当前状态图片 (p - 1) = 1) - 启动线程 (&子程序检测账号EX, p - 1, ) - 程序_延时 (10) - .如果真结束 - -.计次循环尾 () - - -.子程序 _全选_被选择 -.局部变量 P, 整数型 - -.计次循环首 (超级列表框1.取表项数 (), P) - 系统_处理事件 () - 超级列表框1.置状态图片 (P - 1, 1) -.计次循环尾 () - -.子程序 _反选_被选择 -.局部变量 P, 整数型 - -.计次循环首 (超级列表框1.取表项数 (), P) - 系统_处理事件 () - .如果 (超级列表框1.取当前状态图片 (P - 1) = 0) - 超级列表框1.置状态图片 (P - 1, 1) - - .否则 - 超级列表框1.置状态图片 (P - 1, 0) - .如果结束 - -.计次循环尾 () - - -.子程序 _一键获取游戏名_被选择 -.局部变量 p, 整数型 - -.计次循环首 (超级列表框1.取表项数 (), p) - .如果真 (超级列表框1.取当前状态图片 (p - 1) = 1) - 启动线程 (&子程序获取昵称EX, p - 1, ) - 程序_延时 (10) - .如果真结束 - -.计次循环尾 () - -.子程序 子程序获取昵称EX -.参数 索引EX, 整数型 -.局部变量 局_文本, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_uid, 文本型 -.局部变量 nick, 文本型 -.局部变量 str, 文本型 -.局部变量 roleName, 文本型 -.局部变量 余额, 文本型 -.局部变量 areaName, 文本型 -.局部变量 platName, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 局_ctn, 文本型 - -全临界.进入 () -局_文本 = 超级列表框1.取标题 (索引EX, 1) -局_ctn = 超级列表框1.取标题 (索引EX, 5) -全临界.退出 () -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 状态条1.置文本 (0, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_uid = 局_F [2] -局_Cookie = 局_F [3] - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/tencent/bindInfo?actAlias=20260120QYOOB”, , , 局_Cookie, , #常量3)) -' 调试输出 (str) -全临界.进入 () -状态条1.置文本 (0, “是否绑定-> ” + str) -roleName = 文本_取出中间文本 (str, “roleName” + #引号 + “:” + #引号, #引号) -超级列表框1.置标题 (索引EX, 2, roleName) -全临界.退出 () - -' {"error":0,"msg":"success","data":{"bindAccount":1,"bindRole":1,"bindAct":1,"needBindRole":null,"txAct":{"txActId":2811,"gameId":"cjm","gameName":"和平精英","bindType":1},"gameAccount":{"bindType":2,"type":"","faceuri":"https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTI4cIOxb4f7vpSkqYCIIvY1EJTgkhS0ZhVzzJSl2LzDpUzVBJKiaDjvuzpdS6cadAvA6bnrYwZ7jlQ/132","nick":"zicoo"},"gameRole":{"roleName":"白菜被拱了呀","areaName":"微信","platName":"安卓(android)","partitionName":""},"isGranted":null,"gameAuthScene":null,"canChangeRole":0,"changeRoleWaitTime":2490528},"redirectUrl":null} - - -' nick = 文本_取出中间文本 (str, “nick” + #引号 + “:” + #引号, #引号) -' areaName = 文本_取出中间文本 (str, “areaName” + #引号 + “:” + #引号, #引号) -' platName = 文本_取出中间文本 (str, “platName” + #引号 + “:” + #引号, #引号) - - -.子程序 _按钮_刷新商品1_被单击 - -启动线程 (&商品加列表, , ) - -.子程序 商品加列表 -.局部变量 局_商品名, 文本型 - -局_商品名 = 组合框1.取项目文本 (组合框1.现行选中项) -超级列表框1.置标题 (超级列表框1.现行选中项, 3, 局_商品名) - -.子程序 _按钮_启动_被单击 - -.判断开始 (按钮_启动.标题 = “批量兑换商品[列表勾选]”) - .如果真 (超级列表框1.取表项数 () ≤ 0) - 返回 () - .如果真结束 - - 按钮_启动.禁止 = 真 - .如果真 (线程_创建 (&工作线程) = 假) - 按钮_启动.禁止 = 假 - 返回 () - .如果真结束 - -.判断 (按钮_启动.标题 = “停止兑换商品”) - 按钮_启动.禁止 = 真 - 按钮_启动.标题 = “停 止 中...” - 全工作中 = 假 - 工作线程池EX.销毁 () - 返回 () -.默认 - -.判断结束 - - -.子程序 工作线程 -.局部变量 bool, 逻辑型 -.局部变量 int, 整数型 -.局部变量 任务数, 整数型 -.局部变量 局_文本txt, 文本型 -.局部变量 局_data, 文本型 -.局部变量 返回用户名, 文本型 -.局部变量 返回Cookie, 文本型 -.局部变量 返回商品名称, 文本型 -.局部变量 返回商品价格, 文本型 -.局部变量 返回商品ID, 文本型 - -全定时数 = 0 -按钮_启动.标题 = “兑换中...” -状态条1.置文本 (0, “线程启动中...”) -bool = 工作线程池EX.创建 (50, 50, , 真, , 1024 × 128) -.如果真 (bool = 假) - 状态条1.置文本 (0, “初始化工作线程池失败!”) - 按钮_启动.标题 = “批量兑换商品[列表勾选]” - 按钮_启动.禁止 = 假 - 返回 () -.如果真结束 - -全工作中 = 真 -按钮_启动.标题 = “停止兑换商品” -按钮_启动.禁止 = 假 - -int = 0 -.判断循环首 (全工作中 = 真) - 任务数 = 工作线程池EX.取_执行线程数 () + 工作线程池EX.取_队列任务数 () - 任务数 = 工作线程池EX.取_最大线程容量 () - 任务数 - .如果真 (任务数 > 0) - .如果真 (超级列表框1.取当前状态图片 (int) = 1) - 工作线程池EX.投递任务 (&线程子程序, int) - .如果真结束 - - int = int + 1 - - .如果真结束 - - .如果真 (int ≥ 超级列表框1.取表项数 ()) - 跳出循环 () - .如果真结束 - - _延迟 (1) -.判断循环尾 () -.循环判断首 () - 程序_延时 (300) -.循环判断尾 (工作线程池EX.取_是否完全空闲 () = 假) -状态条1.置文本 (0, “正在销毁工作线程池...”) -工作线程池EX.销毁 () -状态条1.置文本 (0, “销毁工作线程池成功!”) -按钮_启动.标题 = “批量兑换商品[列表勾选]” -按钮_启动.禁止 = 假 -状态条1.置文本 (0, “执行停止完毕!”) -.如果真 (选择框_定时抢购.选中 = 真) - 时钟1.时钟周期 = 0 - 选择框_定时抢购.选中 = 假 - 状态条1.置文本 (1, “定时操作完毕!”) -.如果真结束 - - -.子程序 处理Cookie, 逻辑型 -.参数 参_data, 文本型 -.参数 返回用户名, 文本型, 参考 -.参数 返回Cookie, 文本型, 参考 -.局部变量 F_F, 文本型, , "0" - -F_F = 分割文本 (参_data, “----”, ) -.如果真 (取数组成员数 (F_F) < 3) - 返回Cookie = “Cookie格式错误” - 返回 (假) -.如果真结束 - -返回用户名 = F_F [1] -返回Cookie = F_F [3] -返回 (真) - -.子程序 处理商品, 逻辑型 -.参数 参_data, 文本型 -.参数 返回商品名称, 文本型, 参考 -.参数 返回商品价格, 文本型, 参考 -.参数 返回商品ID, 文本型, 参考 -.局部变量 F_F, 文本型, , "0" - -F_F = 分割文本 (参_data, “一”, ) -.如果真 (取数组成员数 (F_F) < 3) - 返回商品ID = “商品格式错误” - 返回 (假) -.如果真结束 - -返回商品名称 = F_F [1] -返回商品价格 = F_F [2] -返回商品ID = F_F [3] -返回 (真) - -.子程序 子程序等待定时, , , 暂不使用 -.局部变量 P, 整数型 -.局部变量 N, 整数型 -.局部变量 局_兑换状态, 文本型 - -.计次循环首 (到整数 (删首尾空 (编辑框_定时秒.内容)), P) - 系统_处理事件 () - 状态条1.置文本 (0, “已设置定时:” + 编辑框_定时秒.内容 + “秒,开始计时/” + 到文本 (P)) - 程序_延时 (1000) -.计次循环尾 () -.计次循环首 (超级列表框1.取表项数 (), N) - 系统_处理事件 () - 全临界.进入 () - 局_兑换状态 = 超级列表框1.取标题 (N - 1, 4) - 全临界.退出 () - .如果真 (局_兑换状态 ≠ “兑换成功”) - 超级列表框1.置状态图片 (N - 1, 1) - .如果真结束 - -.计次循环尾 () - -.子程序 线程子程序 -.参数 参_索引, 整数型 -.局部变量 局_data, 文本型 -.局部变量 F_F, 文本型, , "0" -.局部变量 局_ctnEX, 文本型 -.局部变量 csrf_token, 文本型 -.局部变量 randstr, 文本型 -.局部变量 heardes, 文本型 -.局部变量 body, 文本型 -.局部变量 str, 文本型 -.局部变量 局_xy, 文本型 -.局部变量 roleName, 文本型 -.局部变量 str2, 文本型 -.局部变量 areaName, 文本型 -.局部变量 platName, 文本型 -.局部变量 优化价格, 文本型 -.局部变量 局_bin, 字节集 -.局部变量 局_文本txt, 文本型 -.局部变量 F_F2, 文本型, , "0" -.局部变量 ctnEX, 文本型 -.局部变量 COOK, 文本型 -.局部变量 yyjson, json对象 -.局部变量 error, 文本型 -.局部变量 msg, 文本型 -.局部变量 i, 整数型 -.局部变量 返回用户名, 文本型 -.局部变量 返回Cookie, 文本型 -.局部变量 返回商品名称, 文本型 -.局部变量 返回商品价格, 文本型 -.局部变量 返回商品ID, 文本型 - -.如果真 (全工作中 = 假) - 返回 () -.如果真结束 - -全线程临界.进入 () -超级列表框1.置状态图片 (参_索引, 0) -局_data = 超级列表框1.取标题 (参_索引, 1) -局_文本txt = 超级列表框1.取标题 (参_索引, 3) -' 超级列表框1.保证显示 (参_索引) -全线程临界.退出 () -.如果真 (处理Cookie (局_data, 返回用户名, 返回Cookie) = 假) - 窗口_置状态信息 (参_索引, 1, 返回Cookie) - 返回 () -.如果真结束 - -.如果真 (处理商品 (局_文本txt, 返回商品名称, 返回商品价格, 返回商品ID) = 假) - 窗口_置状态信息 (参_索引, 1, 返回商品ID) - 返回 () -.如果真结束 - - - -ctnEX = 文本_取出中间文本 (返回Cookie, “acf_ccn=”, “;”) -' csrf_token = Getcsrf_token222 (局_Cookie) -全线程临界.进入 () -csrf_token = 超级列表框1.取标题 (参_索引, 6) -.如果真 (csrf_token = “”) - 窗口_置状态信息 (参_索引, 1, “csrf_token获取失败”) - 全线程临界.退出 () - 返回 () -.如果真结束 - -.如果 (ctnEX ≠ “”) - COOK = 返回Cookie + “; acf_ccn=” + ctnEX + “; cvl_csrf_token=” + csrf_token - -.否则 - COOK = 返回Cookie + “; cvl_csrf_token=” + csrf_token -.如果结束 - -' '状态条1.置文本 (0, “正在兑换商品-> ” + 局_商品ID) - -置随机数种子 () -randstr = 文本_取随机字符 (16, 位或 (1, 2, 4)) -heardes = 子文本替换 (#常量12, “[randstr]”, randstr, , , 真) -body = 文本_替换 (#常量11, , , , “[randstr]”, randstr, “[manualID]”, “G4KA4Qnz4LDp7”, “[商品ID]”, 返回商品ID, “[token]”, csrf_token) -全线程临界.退出 () - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/wgapi/ordnc/activity/peace/exchange”, 1, body, COOK, , heardes)) - - -.如果真 (寻找文本 (str, “error” + #引号 + “:0”, , 假) = -1) - .计次循环首 (8, i) - str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/wgapi/ordnc/activity/peace/exchange”, 1, body, COOK, , heardes)) - ' '调试输出 (str) - 窗口_置状态信息 (参_索引, 1, “【” + 到文本 (i) + “】-> ” + str) - .如果真 (寻找文本 (str, “无效”, , 假) ≠ -1 或 寻找文本 (str, “点击太快”, , 假) ≠ -1 或 str = “”) - 全线程临界.进入 () - csrf_token = 超级列表框1.取标题 (参_索引, 6) - ' csrf_token = Getcsrf_token222 (局_Cookie) - .如果真 (csrf_token ≠ “”) - COOK = 选择 (ctnEX ≠ “”, 返回Cookie + “; acf_ccn=” + ctnEX + “; cvl_csrf_token=” + csrf_token, 返回Cookie + “; cvl_csrf_token=” + csrf_token) - - randstr = 文本_取随机字符 (16, 位或 (1, 2, 4)) - heardes = 子文本替换 (#常量12, “[randstr]”, randstr, , , 真) - ' ’下次更新这里 替换#常量11得提交内容 里面得房间ID - body = 文本_替换 (#常量11, , , , “[randstr]”, randstr, “[manualID]”, “G4KA4Qnz4LDp7”, “[商品ID]”, 返回商品ID, “[token]”, csrf_token) - - .如果真结束 - - 全线程临界.退出 () - - .如果真结束 - .如果真 (寻找文本 (str, “error” + #引号 + “:0”, , 假) ≠ -1) - 跳出循环 () - .如果真结束 - - 程序_延时 (300) - .计次循环尾 () - - .' 判断循环首 (真) - .' 如果真 (全工作中 = 假) - ' 返回 () - .如果真结束 - - ' i = i + 1 - ' str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/wgapi/ordnc/activity/peace/exchange”, 1, body, COOK, , heardes)) - ' ' '调试输出 (str) - ' 窗口_置状态信息 (参_索引, 1, “【” + 到文本 (i) + “】-> ” + str) - .' 如果真 (寻找文本 (str, “无效”, , 假) ≠ -1 或 寻找文本 (str, “点击太快”, , 假) ≠ -1 或 str = “”) - ' 全线程临界.进入 () - ' csrf_token = 超级列表框1.取标题 (参_索引, 6) - ' ' csrf_token = Getcsrf_token222 (局_Cookie) - .' 如果真 (csrf_token ≠ “”) - ' COOK = 选择 (ctnEX ≠ “”, 返回Cookie + “; acf_ccn=” + ctnEX + “; cvl_csrf_token=” + csrf_token, 返回Cookie + “; cvl_csrf_token=” + csrf_token) - - ' randstr = 文本_取随机字符 (16, 位或 (1, 2, 4)) - ' heardes = 子文本替换 (#常量12, “[randstr]”, randstr, , , 真) - ' ' ’下次更新这里 替换#常量11得提交内容 里面得房间ID - ' body = 文本_替换 (#常量11, , , , “[randstr]”, randstr, “[manualID]”, “G4KA4Qnz4LDp7”, “[商品ID]”, 返回商品ID, “[token]”, csrf_token) - - .如果真结束 - - ' 全线程临界.退出 () - - .如果真结束 - - .' 如果真 (寻找文本 (str, “error” + #引号 + “:0”, , 假) ≠ -1) - ' 跳出循环 () - .如果真结束 - - ' 程序_延时 (100) - ' 系统_处理事件 () - .' 判断循环尾 () - -.如果真结束 - - - -.如果 (寻找文本 (str, “error” + #引号 + “:0”, , 假) ≠ -1) - 窗口_置状态信息 (参_索引, 1, “兑换成功”) - .计次循环首 (2, ) - str2 = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/tencent/bindInfo?actAlias=20260120QYOOB”, , , 返回Cookie, , #常量3)) - .如果真 (str2 ≠ “”) - 跳出循环 () - .如果真结束 - - .计次循环尾 () - .如果真 (str2 ≠ “”) - yyjson.清空 () - yyjson.解析 (str2) - roleName = yyjson.取文本 (“data/gameRole/roleName”) - 全线程临界.进入 () - 优化价格 = 取文本左边 (返回商品价格, 取文本长度 (返回商品价格) - 1) - 保存日志2 (时间_到文本 (取现行时间 (), 1) + “ ” + 返回用户名 + “----” + roleName + “----” + 返回商品名称 + “----” + 优化价格) - 局_bin = 文转图片P (返回商品名称 + “ ” + #换行符 + 时间_格式化 (取现行时间 (), “yyyy年MM月dd日”, “ hh:mm:ss”, 真) + #换行符 + “兑换账号:” + roleName + “(” + 返回用户名 + “)”) - 写到文件_ (全PIC + “\” + roleName + “-” + 返回商品名称 + “.png”, 局_bin) - 全线程临界.退出 () - .如果真结束 - - -.否则 - 窗口_置状态信息 (参_索引, 1, str) - -.如果结束 - - -.子程序 Getcsrf_token222, 文本型 -.参数 参_Cookie, 文本型 -.局部变量 局_文本, 文本型 -.局部变量 局_CCK, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 str, 文本型 -.局部变量 返回CK, 文本型 -.局部变量 csrf_token, 文本型 - -str = 到文本 (网页_访问_对象 (“https://www.douyu.com/japi/carnival/nc/common/generateCsrf”, 1, , 参_Cookie, 返回CK, #常量10)) -csrf_token = 文本_取出中间文本 (返回CK, “cvl_csrf_token=”, “;”) -' '调试输出 (“csrf_token---”, csrf_token) -返回 (csrf_token) - -.子程序 _一键查询换绑时间_被选择 -.局部变量 p, 整数型 - -.计次循环首 (超级列表框1.取表项数 (), p) - 系统_处理事件 () - .如果真 (超级列表框1.取当前状态图片 (p - 1) = 1) - 启动线程 (&子程序查换绑时间, p - 1, ) - 程序_延时 (10) - .如果真结束 - -.计次循环尾 () - -.子程序 子程序查换绑时间 -.参数 索引E, 整数型 -.局部变量 局_文本, 文本型 -.局部变量 局_ctn, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_uid, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 str, 文本型 -.局部变量 yyjson, json对象 -.局部变量 changeRoleWaitTime, 整数型 -.局部变量 timetxt, 文本型 -.局部变量 局_txt, 文本型 - -全临界.进入 () -局_文本 = 超级列表框1.取标题 (索引E, 1) -局_ctn = 超级列表框1.取标题 (索引E, 5) -全临界.退出 () -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 状态条1.置文本 (0, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_uid = 局_F [2] -局_Cookie = 局_F [3] -' 'actAlias=20220616CJSZU -' actAlias=20260120QYOOB -' actAlias=20250213NQCYX -' https://www.douyu.com/japi/carnivalApi/tencent/bindInfo?actAlias=20260120QYOOB - -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/japi/carnivalApi/v2/tencent/bindInfo?actAlias=20260120QYOOB”, , , 局_Cookie, , #常量3)) -' 调试输出 (str) -yyjson.清空 () -yyjson.解析 (str) -.如果 (yyjson.取文本 (“msg”) = “success”) - changeRoleWaitTime = yyjson.取整数 (“data/changeRoleWaitTime”) - timetxt = 时间_秒到时分秒格式 (changeRoleWaitTime) - 窗口_置状态信息 (索引E, 2, “释放时间:” + timetxt) - -.否则 - 窗口_置状态信息 (索引E, 2, “查询失败”) -.如果结束 - - -.子程序 _一键查询限兑商品_被选择 -.局部变量 p, 整数型 - -.计次循环首 (超级列表框1.取表项数 (), p) - 系统_处理事件 () - .如果真 (超级列表框1.取当前状态图片 (p - 1) = 1) - 启动线程 (&子程序查限兑商品, p - 1, ) - 程序_延时 (10) - .如果真结束 - -.计次循环尾 () - -.子程序 子程序查限兑商品 -.参数 索引E, 整数型 -.局部变量 局_文本, 文本型 -.局部变量 局_ctn, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_uid, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 str, 文本型 -.局部变量 yyjson, json对象 -.局部变量 changeRoleWaitTime, 整数型 -.局部变量 timetxt, 文本型 -.局部变量 zy数, 整数型 -.局部变量 statustxt, 文本型 -.局部变量 P, 整数型 -.局部变量 F_F, 文本型, , "0" -.局部变量 commodityName, 文本型 -.局部变量 排序E, 文本型 - -全临界.进入 () -局_文本 = 超级列表框1.取标题 (索引E, 1) -局_ctn = 超级列表框1.取标题 (索引E, 5) -全临界.退出 () -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 状态条1.置文本 (0, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_uid = 局_F [2] -局_Cookie = 局_F [3] - -' data.list[21].status = 0 -' manualID=G4KA4Qnz4LDp7 -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/wgapi/ordnc/activity/peace/storehome?manualID=G4KA4Qnz4LDp7&rid=9263298”, , , 局_Cookie, , #常量3)) -' 调试输出 (str) -yyjson.清空 () -yyjson.解析 (str) -zy数 = yyjson.取成员数 (“data/list”) -.计次循环首 (zy数, P) - 系统_处理事件 () - statustxt = yyjson.取文本 (“data/list/” + 到文本 (P - 1) + “/status”) - .如果真 (statustxt = “1”) - commodityName = yyjson.取文本 (“data/list/” + 到文本 (P - 1) + “/commodityName”) - 加入成员 (F_F, commodityName) - .如果真结束 - -.计次循环尾 () -.如果真 (取数组成员数 (F_F) < 1) - 窗口_置状态信息 (索引E, 2, “无限制商品”) - ' 状态条1.置文本 (0, “限兑-> 无限制商品”) - 返回 () -.如果真结束 - -排序E = 数组_合并 (F_F, “,”) -窗口_置状态信息 (索引E, 2, “限兑*” + 到文本 (取数组成员数 (F_F)) + “:” + 排序E) -' 状态条1.置文本 (0, “限兑*” + 到文本 (取数组成员数 (F_F)) + “:” + 排序E) -返回 () - -.子程序 _一键查询鱼刺余额_被选择 -.局部变量 p, 整数型 - -.计次循环首 (超级列表框1.取表项数 (), p) - .如果真 (超级列表框1.取当前状态图片 (p - 1) = 1) - 启动线程 (&子程序查询鱼刺, p - 1, ) - 程序_延时 (100) - .如果真结束 - -.计次循环尾 () - -.子程序 子程序查询鱼刺 -.参数 索引E -.局部变量 局_文本, 文本型 -.局部变量 局_ctn, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_uid, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 str, 文本型 -.局部变量 yyjson, json对象 -.局部变量 局_余额, 文本型 - -全临界.进入 () -局_文本 = 超级列表框1.取标题 (索引E, 1) -局_ctn = 超级列表框1.取标题 (索引E, 5) -全临界.退出 () -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 状态条1.置文本 (0, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_uid = 局_F [2] -局_Cookie = 局_F [3] -窗口_置状态信息 (索引E, 1, “查询鱼刺余额...”) -str = 到文本 (网页_访问_对象 (“https://cz.douyu.com/item/gold/account”, , , 局_Cookie, , #常量2)) -' 调试输出 (str) -yyjson.清空 () -yyjson.解析 (str) -局_余额 = yyjson.取文本 (“data/gold”) -窗口_置状态信息 (索引E, 1, “鱼刺余额:” + 到文本 (局_余额)) - - -.子程序 _时钟1_周期事件 -.局部变量 设置定时关闭, 文本型 -.局部变量 动态时间, 文本型 -.局部变量 设置定时开始, 文本型 - -设置定时开始 = 删首尾空 (编辑框_时.内容) + “:” + 删首尾空 (编辑框_分.内容) + “:” + 删首尾空 (编辑框_秒.内容) -动态时间 = 时间_格式化 (取现行时间 (), , “hh:mm:ss”, 真) -状态条1.置文本 (1, “[定时脚本]动态时间:” + 动态时间) - - -.如果真 (到整数 (编辑框_分.内容) - 1 = 取分钟 (取现行时间 ())) - .如果真 (全已取crtoken = 假) - _全选_被选择 () - _一键获取兑换csrftoken_被选择 () - 全已取crtoken = 真 - - .如果真结束 - -.如果真结束 - -.如果真 (动态时间 = 设置定时开始) - _按钮_启动_被单击 () -.如果真结束 - - -.子程序 _选择框_定时抢购_被单击 - -.如果 (选择框_定时抢购.选中 = 真) - _全选_被选择 () - 全已取crtoken = 假 - 时钟1.时钟周期 = 1000 - 状态条1.置文本 (1, “已开启定时抢购√”) - -.否则 - 全已取crtoken = 真 - 时钟1.时钟周期 = 0 - 状态条1.置文本 (1, “已关闭定时抢购×”) - 工作中 = 假 - 工作线程池EX.销毁 () -.如果结束 - - -.子程序 _开通精英宝典30_被选择 -.局部变量 局_文本, 文本型 -.局部变量 ctnEX, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_Cookie, 文本型 - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -ctnEX = 超级列表框1.取标题 (超级列表框1.现行选中项, 5) -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_Cookie = 局_F [3] -精英二维码30 (ctnEX, 局_Cookie) - - -.子程序 _一键查询兑换记录_被选择 -.局部变量 p, 整数型 - -.计次循环首 (超级列表框1.取表项数 (), p) - .如果真 (超级列表框1.取当前状态图片 (p - 1) = 1) - 启动线程 (&子程序查询兑换记录, p - 1, ) - 程序_延时 (100) - .如果真结束 - -.计次循环尾 () - - -.子程序 子程序查询兑换记录 -.参数 索引E -.局部变量 局_文本, 文本型 -.局部变量 局_ctn, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_uid, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 str, 文本型 -.局部变量 yyjson, json对象 -.局部变量 局_余额, 文本型 -.局部变量 zy数, 整数型 -.局部变量 P, 整数型 -.局部变量 F_F, 文本型, , "0" -.局部变量 commodityName, 文本型 -.局部变量 排序E, 文本型 - -全临界.进入 () -局_文本 = 超级列表框1.取标题 (索引E, 1) -局_ctn = 超级列表框1.取标题 (索引E, 5) -全临界.退出 () -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 状态条1.置文本 (0, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_uid = 局_F [2] -局_Cookie = 局_F [3] -窗口_置状态信息 (索引E, 1, “查询兑换记录...”) -' manualID=G4KA4Qnz4LDp7 -str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/wgapi/ordnc/activity/peace/exchangeList?manualID=G4KA4Qnz4LDp7&limit=100&offset=0”, , , 局_Cookie, , #常量3)) -' '调试输出 (str) -yyjson.清空 () -yyjson.解析 (str) -zy数 = yyjson.取成员数 (“data/list”) -.计次循环首 (zy数, P) - commodityName = yyjson.取文本 (“data/list/” + 到文本 (P - 1) + “/commodityName”) - 加入成员 (F_F, commodityName) -.计次循环尾 () -.如果真 (取数组成员数 (F_F) < 1) - 窗口_置状态信息 (索引E, 2, “无兑换记录”) - 返回 () -.如果真结束 - -排序E = 数组_合并 (F_F, “,”) -窗口_置状态信息 (索引E, 2, “记录*” + 到文本 (取数组成员数 (F_F)) + “:” + 排序E) - - - -.子程序 _充值鱼刺Api_被选择 -.局部变量 返回积分, 文本型 -.局部变量 局_充值账号, 文本型 -.局部变量 局_文本, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 局_Cookie, 文本型 -.局部变量 返回充值前余额, 文本型 -.局部变量 返回充值后余额, 文本型 -.局部变量 冲之前余额, 文本型 -.局部变量 充值后余额, 文本型 - -局_文本 = 超级列表框1.取标题 (超级列表框1.现行选中项, 1) -局_充值账号 = 文本_取左边 (局_文本, “----”) -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “Cookie格式错误”) - 返回 () -.如果真结束 - -局_Cookie = 局_F [3] - -' 返回积分 = 查积分记录 () -.' 如果真 (返回积分 = “NULL”) - ' 窗口_置状态信息 (超级列表框1.现行选中项, 2, “未开通精英手册”) - ' 返回 () -.如果真结束 - -.' 如果真 (到整数 (返回积分) < 10) - ' 窗口_置状态信息 (超级列表框1.现行选中项, 2, “未开通精英手册”) - .' 如果真 (信息框 (“积分:” + 返回积分 + “,是否充值?”, #信息图标 + #确认钮 + #取消钮, , ) = #取消钮) - ' 返回 () - .如果真结束 - -.如果真结束 - - - -返回充值前余额 = 查询鱼刺余额 (局_Cookie) -冲之前余额 = 到文本 (到整数 (返回充值前余额) ÷ 100) -.如果真 (冲之前余额 = “”) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “查询余额失败”) - 返回 () -.如果真结束 - -.如果真 (信息框 (“充值数量:” + 编辑框_充值金额.内容 + “,是否充值?”, #信息图标 + #确认钮 + #取消钮, , ) = #取消钮) - 返回 () -.如果真结束 - - -窗口_置状态信息 (超级列表框1.现行选中项, 2, “充值前鱼刺:” + 冲之前余额 + “,正在充值...”) -程序_延时 (1000) -.如果真 (api充值 (超级列表框1.现行选中项, 局_充值账号) = 真) - .计次循环首 (10, ) - 返回充值后余额 = 查询鱼刺余额 (局_Cookie) - 充值后余额 = 到文本 (到整数 (返回充值后余额) ÷ 100) - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “充值前鱼刺:” + 冲之前余额 + “,等待充值后余额:” + 充值后余额) - .如果真 (充值后余额 ≠ 冲之前余额) - 跳出循环 () - .如果真结束 - 程序_延时 (1000) - .计次循环尾 () - 窗口_置状态信息 (超级列表框1.现行选中项, 2, “充值成功后鱼刺:” + 充值后余额) - 程序_延时 (1000) - 直接送礼物 (局_Cookie, 超级列表框1.现行选中项) - 程序_延时 (2000) - .计次循环首 (3, ) - 查积分记录 () - .计次循环尾 () -.如果真结束 - - -.子程序 api充值, 逻辑型 -.参数 参_索引, 整数型 -.参数 参_充值账号, 文本型 -.局部变量 timestamp, 文本型 -.局部变量 random, 文本型 -.局部变量 订单时间ordersn, 文本型 -.局部变量 secretKey, 文本型 -.局部变量 sign, 文本型 -.局部变量 body, 文本型 -.局部变量 str, 文本型 -.局部变量 yyjson, json对象 -.局部变量 ordersn, 文本型 -.局部变量 bool, 逻辑型 -.局部变量 i, 整数型 -.局部变量 局_充值数量, 文本型 -.局部变量 返回err0, 文本型 -.局部变量 dealer_id, 文本型 - -dealer_id = 删全部空 (编辑框_经销商ID.内容) -secretKey = 删全部空 (编辑框_API密钥.内容) -.如果真 (dealer_id = “”) - 窗口_置状态信息 (参_索引, 2, “请设置经销商ID~!”) - 返回 (假) -.如果真结束 - -.如果真 (secretKey = “”) - 窗口_置状态信息 (参_索引, 2, “请设置API密钥~!”) - 返回 (假) -.如果真结束 - -局_充值数量 = 删全部空 (编辑框_充值金额.内容) -.如果真 (局_充值数量 = “”) - 窗口_置状态信息 (参_索引, 2, “请设置充值数量~!”) - 返回 (假) -.如果真结束 - -timestamp = 时间_取现行时间戳 () -random = 文本_取随机字符 (13, 位或 (1, 2)) -订单时间ordersn = timestamp -sign = 校验_取md5_文本 (secretKey + “dealer_id=” + dealer_id + “&game_id=37¬ify_url=https://www.baidu.com&number=” + 局_充值数量 + “&ordersn=” + 订单时间ordersn + “&random=” + random + “&rid=” + 参_充值账号 + “&rules_id=317&server=默认区服×tamp=” + timestamp + secretKey, 真, 真) - -body = “dealer_id=” + dealer_id + “&game_id=37¬ify_url=https://www.baidu.com&number=” + 局_充值数量 + “&ordersn=” + 订单时间ordersn + “&random=” + random + “&rid=” + 参_充值账号 + “&rules_id=317&server=默认区服×tamp=” + timestamp + “&signature=” + sign - -str = 编码_Utf8到Ansi (网页_访问_对象 (“http://api.hapu.cc/order/createOrder”, 1, body, , , “User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36” + #换行符 + “Content-Type: application/x-www-form-urlencoded”)) -yyjson.清空 () -yyjson.解析 (str) -ordersn = yyjson.取文本 (“ordersn”) -.如果真 (ordersn ≠ “”) - 窗口_置状态信息 (参_索引, 2, “api下单成功”) - 返回 (真) - -.如果真结束 - -窗口_置状态信息 (参_索引, 2, “api下单失败:” + 编码_usc2到ansi (str)) -返回 (假) - -' {"status":200,"msg":"成功","ordersn":"1746864258996","fy_order_id":"20250510160420546837090","money":"0.980"} - -.子程序 查询充值结果, 逻辑型, , {"status":200,"msg":"成功","ordersn":"1746864258996","fy_order_id":"20250510160420546837090","money":"0.980"} -.参数 参_ordersn, 文本型 -.参数 返回err0, 文本型 -.局部变量 str, 文本型 -.局部变量 body, 文本型 -.局部变量 random, 文本型 -.局部变量 timestamp, 文本型 -.局部变量 secretKey, 文本型 -.局部变量 sign, 文本型 -.局部变量 yyjson, json对象 -.局部变量 msg, 文本型 - -timestamp = 时间_取现行时间戳 () -random = 文本_取随机字符 (13, 位或 (1, 2)) -secretKey = “403710daec035bbd94e30cefb337b6ccded16dbf” -sign = 校验_取md5_文本 (secretKey + “dealer_id=129873564&ordersn=” + 参_ordersn + “&random=” + random + “×tamp=” + timestamp + secretKey, 真, 真) - -body = “dealer_id=129873564&ordersn=” + 参_ordersn + “&random=” + random + “×tamp=” + timestamp + “&signature=” + sign -str = 编码_Utf8到Ansi (网页_访问_对象 (“http://api.hapu.cc/order/getorder”, 1, body, , , “User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36” + #换行符 + “Content-Type: application/x-www-form-urlencoded”)) -' 调试输出 (str) -yyjson.清空 () -yyjson.解析 (str) -msg = yyjson.取文本 (“msg”) -返回err0 = msg -.如果真 (msg = “成功”) - 返回 (真) -.如果真结束 - -返回 (假) - -.子程序 查询鱼刺余额, 文本型, , {"status":200,"msg":"成功","ordersn":"1746864258996","fy_order_id":"20250510160420546837090","money":"0.980"} -.参数 参_Cookie, 文本型 -.局部变量 str, 文本型 -.局部变量 yyjson, json对象 -.局部变量 count, 文本型 - -.计次循环首 (3, ) - str = 编码_Utf8到Ansi (网页_访问_对象 (“https://www.douyu.com/wjapi/nc/exchange/fim?appCode=YJTX”, , , 参_Cookie, , “Host: www.douyu.com” + #换行符 + “Connection: keep-alive” + #换行符 + “sec-ch-ua-platform: ” + #引号 + “Windows” + #引号 + “” + #换行符 + “User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36” + #换行符 + “Accept: application/json, text/plain, */*” + #换行符 + “Referer: https://www.douyu.com/member/walletcenter”)) - .如果真 (str ≠ “”) - 跳出循环 () - .如果真结束 - -.计次循环尾 () -调试输出 (str) -yyjson.清空 () -yyjson.解析 (str) -count = yyjson.取文本 (“data/count”) -返回 (count) - - -.子程序 _一键获取兑换csrftoken_被选择 -.局部变量 p, 整数型 -.局部变量 局_句柄, 整数型 -.局部变量 arr0, 整数型, , "0" -.局部变量 i, 整数型 - -工作线程取token.创建 (50) -.计次循环首 (超级列表框1.取表项数 (), p) - 系统_处理事件 () - .如果真 (超级列表框1.取当前状态图片 (p - 1) = 1) - 工作线程取token.投递任务 (&Getcsrf_token3333, p - 1) - ' '启动线程 (&Getcsrf_token3333, p - 1, 局_句柄) - 程序_延时 (10) - - .如果真结束 - -.计次循环尾 () -.循环判断首 () - 程序_延时 (300) -.循环判断尾 (工作线程取token.取_是否完全空闲 () = 假) -全已取crtoken = 真 -程序_延时 (1000) -_全选_被选择 () - -.子程序 Getcsrf_token3333 -.参数 参_索引, 整数型 -.局部变量 局_文本, 文本型 -.局部变量 局_Cookie, 文本型 -.局部变量 局_F, 文本型, , "0" -.局部变量 str, 文本型 -.局部变量 返回CK, 文本型 -.局部变量 csrf_token, 文本型 - -超级列表框1.置状态图片 (参_索引, 0) -局_文本 = 超级列表框1.取标题 (参_索引, 1) -局_F = 分割文本 (局_文本, “----”, ) -.如果真 (取数组成员数 (局_F) < 3) - 全Fast_list.进入写锁 () - 超级列表框1.置标题 (参_索引, 4, “Cookie无效”) - 全Fast_list.退出写锁 () - 返回 () -.如果真结束 - -局_Cookie = 局_F [3] -str = 到文本 (网页_访问_对象 (“https://www.douyu.com/japi/carnival/nc/common/generateCsrf”, 1, , 局_Cookie, 返回CK, #常量10)) -csrf_token = 文本_取出中间文本 (返回CK, “cvl_csrf_token=”, “;”) -状态条1.置文本 (0, “#” + 到文本 (参_索引) + “=>” + csrf_token) -' 调试输出 (csrf_token) -.如果真 (csrf_token ≠ “”) - 全Fast_list.进入写锁 () - 超级列表框1.置标题 (参_索引, 4, “获取csrf_token成功”) - 超级列表框1.置标题 (参_索引, 6, csrf_token) - 全Fast_list.退出写锁 () - 返回 () -.如果真结束 - -全Fast_list.进入写锁 () -超级列表框1.置标题 (参_索引, 4, str) -全Fast_list.退出写锁 () - - -.子程序 _导出Cookie_被选择 - -输入框 (“默认保存在默认在同程序路径下的导出数据目录下,仅输入文件名即可”, “导出文件”, , 导出存放文件名, , ) -.如果真 (导出存放文件名 = “”) - 信息框 (“请输入文件名!”, 0, , ) - 返回 () -.如果真结束 - -保存勾选 () - -.子程序 保存勾选 -.局部变量 导出到文件, 鱼刺类_输出文本 -.局部变量 j_str, 文本型 -.局部变量 开始时间, 整数型 -.局部变量 耗时, 整数型 -.局部变量 N, 整数型 - -开始时间 = 取启动时间 () -状态条1.置文本 (0, “正在导出数据...”) -.计次循环首 (超级列表框1.取表项数 (), N) - .如果真 (超级列表框1.取当前状态图片 (N - 1) = 1) - 全导出X.进入读锁 () - j_str = 超级列表框1.取标题 (N - 1, 1) - 全导出X.退出读锁 () - 导出到文件.写文本行 (j_str, 导出存放文件名, 全目录导出, “.txt”) - .如果真结束 - - 系统_处理事件 () -.计次循环尾 () -导出到文件.关闭所有文件占用 () -耗时 = 取启动时间 () - 开始时间 -状态条1.置文本 (0, “导出数据完成,耗时:” + 到文本 (耗时)) -提示框 (“导出完成”, , , , 1000) - - - -.子程序 _超级列表框1_当前表项被改变 - - diff --git a/pyproject.toml b/pyproject.toml index 3d19291..566ac5f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,9 @@ dependencies = [ "python-multipart>=0.0.9", "alembic>=1.18.4", "websockets>=16.0", + "onnxruntime>=1.18.0", + "scipy>=1.13.0", + "pyexecjs>=1.5.1", ] [build-system] diff --git a/uv.lock b/uv.lock index 6c9542b..44b4c28 100644 --- a/uv.lock +++ b/uv.lock @@ -210,13 +210,16 @@ dependencies = [ { name = "fastapi" }, { name = "loguru" }, { name = "numpy" }, + { name = "onnxruntime" }, { name = "opencv-python-headless" }, { name = "pillow" }, { name = "pycryptodome" }, { name = "pydantic" }, + { name = "pyexecjs" }, { name = "python-jose", extra = ["cryptography"] }, { name = "python-multipart" }, { name = "requests", extra = ["socks"] }, + { name = "scipy" }, { name = "sqlalchemy" }, { name = "uvicorn", extra = ["standard"] }, { name = "websockets" }, @@ -229,13 +232,16 @@ requires-dist = [ { name = "fastapi", specifier = ">=0.110.0" }, { name = "loguru", specifier = ">=0.7.0" }, { name = "numpy", specifier = ">=1.24.0" }, + { name = "onnxruntime", specifier = ">=1.18.0" }, { name = "opencv-python-headless", specifier = ">=4.8.0" }, { name = "pillow", specifier = ">=10.0.0" }, { name = "pycryptodome", specifier = ">=3.19.0" }, { name = "pydantic", specifier = ">=2.0.0" }, + { name = "pyexecjs", specifier = ">=1.5.1" }, { name = "python-jose", extras = ["cryptography"], specifier = ">=3.3.0" }, { name = "python-multipart", specifier = ">=0.0.9" }, { name = "requests", extras = ["socks"], specifier = ">=2.31.0" }, + { name = "scipy", specifier = ">=1.13.0" }, { name = "sqlalchemy", specifier = ">=2.0.0" }, { name = "uvicorn", extras = ["standard"], specifier = ">=0.27.0" }, { name = "websockets", specifier = ">=16.0" }, @@ -269,6 +275,14 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6c/ff/8496d9847a5fedae775eb49460722d3efaa80487854273e9647ae876218c/fastapi-0.138.0-py3-none-any.whl", hash = "sha256:b6f54fd1bd72c80b0f899f172c61a600f6f7af9b43d4d772a018f35624048cb0", size = 126779, upload-time = "2026-06-20T01:18:03.483Z" }, ] +[[package]] +name = "flatbuffers" +version = "25.12.19" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/2d/d2a548598be01649e2d46231d151a6c56d10b964d94043a335ae56ea2d92/flatbuffers-25.12.19-py2.py3-none-any.whl", hash = "sha256:7634f50c427838bb021c2d66a3d1168e9d199b0607e6329399f04846d42e20b4", size = 26661, upload-time = "2025-12-19T23:16:13.622Z" }, +] + [[package]] name = "greenlet" version = "3.5.2" @@ -381,6 +395,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/63/cf/5a6d34850a39d1093558564f77ee8e8e0bee5061151b8f05a55711001ec7/numpy-2.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8", size = 10221482, upload-time = "2026-05-18T23:34:25.876Z" }, ] +[[package]] +name = "onnxruntime" +version = "1.27.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "flatbuffers" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "protobuf" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/b7/dd3a524ed93a820dff1af902d0412957ab12499953333e9daa01af5bc480/onnxruntime-1.27.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:a14c2ce45312def86b77aea651f46565e45960cf5f0721bfdff449165086ab76", size = 18433506, upload-time = "2026-06-15T22:43:47.026Z" }, + { url = "https://files.pythonhosted.org/packages/84/86/c3b6b17745a1997d784dadc9bd88d713d2e6721139a5a0e885b28cfb79b1/onnxruntime-1.27.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6fddce0539a4898c7bef35b052ffd37935b2190e35488eab99ce91887743ea1", size = 16438140, upload-time = "2026-06-15T22:42:40.666Z" }, + { url = "https://files.pythonhosted.org/packages/26/81/24dd9b31b0fb912ee19ca53ac1c9764bfd79d58a2ccef564eb693be831a5/onnxruntime-1.27.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c65a7438632d55dfbc8a02ee60bd6cf7dd9d1ba05a43d4b851452f32338e194", size = 18658316, upload-time = "2026-06-15T22:43:04.012Z" }, + { url = "https://files.pythonhosted.org/packages/4f/88/8ec9db1a4d126bb8b758992beb40d1249df171917d75f44a327eb5f20dda/onnxruntime-1.27.0-cp312-cp312-win_amd64.whl", hash = "sha256:20c321cf187ba496e648acf6b4cf90b4d398b0d17c2a77fdaeba365b908cc1c1", size = 13358769, upload-time = "2026-06-15T22:43:34.581Z" }, + { url = "https://files.pythonhosted.org/packages/ae/9f/fdad359dfcba7e7cd8815569b304a596531d4efa77a75d77f8b4981891a2/onnxruntime-1.27.0-cp312-cp312-win_arm64.whl", hash = "sha256:d0d1f68868e2ef30ef70998ba9bbbc5c305e9b17041e3936751c1b8aa6aade06", size = 13104440, upload-time = "2026-06-15T22:43:22.893Z" }, +] + [[package]] name = "opencv-python-headless" version = "4.13.0.92" @@ -399,6 +431,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4a/90/b338326131ccb2aaa3c2c85d00f41822c0050139a4bfe723cfd95455bd2d/opencv_python_headless-4.13.0.92-cp37-abi3-win_amd64.whl", hash = "sha256:77a82fe35ddcec0f62c15f2ba8a12ecc2ed4207c17b0902c7a3151ae29f37fb6", size = 40070414, upload-time = "2026-02-05T07:02:26.448Z" }, ] +[[package]] +name = "packaging" +version = "26.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, +] + [[package]] name = "pillow" version = "12.2.0" @@ -418,6 +459,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/10/e1/542a474affab20fd4a0f1836cb234e8493519da6b76899e30bcc5d990b8b/pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414", size = 2463612, upload-time = "2026-04-01T14:43:39.421Z" }, ] +[[package]] +name = "protobuf" +version = "7.35.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/01/9ef0afd7999eb9badb3a768b4aedd78c86d4c65cfaf1958ab276199e76b4/protobuf-7.35.1.tar.gz", hash = "sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a", size = 458717, upload-time = "2026-06-11T21:55:40.257Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/03/8aeeb7458d22546bf64b5250ca1daeb5ff757d900e8e4a7476c6f0db843e/protobuf-7.35.1-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:24f857477359a85c0c235261b8ba905fd51b2562f4a64ca1df5473f29850cbf6", size = 433226, upload-time = "2026-06-11T21:55:31.719Z" }, + { url = "https://files.pythonhosted.org/packages/37/4b/dfb89eb0e652a1ff073c39a59fb5e3a83cfe9b57a2c83fa6d78270101767/protobuf-7.35.1-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:11d6b0ec246892d85215b0a13ca6e0233cf5284b68f0ac02646427f4ff88a799", size = 328847, upload-time = "2026-06-11T21:55:34.035Z" }, + { url = "https://files.pythonhosted.org/packages/0f/58/dc12f2cd484951524af6e3382c785869b9b3fb5e52ee95ae23add53ee8f9/protobuf-7.35.1-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:b73f9489a4b8b1c9cb1f8ed951c736392592edb24b9d6819f36d2e10b171d5b4", size = 344030, upload-time = "2026-06-11T21:55:34.941Z" }, + { url = "https://files.pythonhosted.org/packages/e4/be/5b3cfe508bfab6761414ff944e3366eb13be4fd71efcd69450f89ba39f43/protobuf-7.35.1-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:74758715c53d7158fb76caf4f0cfdacc5329a4b1bb994f865d6cf302d413a1c4", size = 327130, upload-time = "2026-06-11T21:55:35.921Z" }, + { url = "https://files.pythonhosted.org/packages/d8/bc/6d6c7ba8709c85f8f2c390b2b118d6fb08a783676a572271851bf45a7d22/protobuf-7.35.1-cp310-abi3-win32.whl", hash = "sha256:353652e4efd0bca5b5fc2656abf8307ef351f0cf938c9eba09f0e09c20a25c30", size = 428945, upload-time = "2026-06-11T21:55:37.034Z" }, + { url = "https://files.pythonhosted.org/packages/0a/19/8d0cb6f20a1ef7b18f1c8986ad5783f22f84cce39c6ce9a6e645ea55192e/protobuf-7.35.1-cp310-abi3-win_amd64.whl", hash = "sha256:230a75ddfc2de4806e56696ce9640c1cdfdb6543b7cfce98d42a4c0a0e7bdb87", size = 439996, upload-time = "2026-06-11T21:55:38.123Z" }, + { url = "https://files.pythonhosted.org/packages/19/c7/5f7c636ec43e0c545e28d1f1db71990108306f7bdcb89f069ba97e428e7f/protobuf-7.35.1-py3-none-any.whl", hash = "sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9", size = 171659, upload-time = "2026-06-11T21:55:39.155Z" }, +] + [[package]] name = "pyasn1" version = "0.6.3" @@ -500,6 +556,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, ] +[[package]] +name = "pyexecjs" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ba/8e/aedef81641c8dca6fd0fb7294de5bed9c45f3397d67fddf755c1042c2642/PyExecJS-1.5.1.tar.gz", hash = "sha256:34cc1d070976918183ff7bdc0ad71f8157a891c92708c00c5fbbff7a769f505c", size = 13344, upload-time = "2018-01-18T04:33:55.126Z" } + [[package]] name = "pysocks" version = "1.7.1" @@ -596,6 +661,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, ] +[[package]] +name = "scipy" +version = "1.18.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a7/25/c2700dfaf6442b4effaa91af24ebce5dc9d31bb4a69706313aae70d72cd0/scipy-1.18.0.tar.gz", hash = "sha256:67b2ad2ad54c72ca6d04975a9b2df8c3638c34ddd5b28738e94fc2b57929d378", size = 30774447, upload-time = "2026-06-19T15:01:43.456Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/19/ca10ead60b0acc80b2b833c2c4a4f2ff753d0f58b811f70d911c7e94a25c/scipy-1.18.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:7bd21faaf5a1a3b2eff922d02db5f191b99a6518db9078a8fb23169f6d22259a", size = 31056519, upload-time = "2026-06-19T14:59:45.203Z" }, + { url = "https://files.pythonhosted.org/packages/96/72/1e6442a00cd2924d361aa1b642ab6373ec35c6fabf311a760be9f76e0f13/scipy-1.18.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:265915e79107de9f946b855e50d7470d5893ec3f54b342e1aa6201cbdcd8bb6b", size = 28681889, upload-time = "2026-06-19T14:59:48.103Z" }, + { url = "https://files.pythonhosted.org/packages/9b/2d/11dd93d21e147a73ba22bd75c0b9208d3a2e0ec76d53170ce7d9029b1015/scipy-1.18.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9ab7b758be6940954a713ee466e2043e9f6e2ed965c1fce5c91039f4be3d90a9", size = 20423580, upload-time = "2026-06-19T14:59:50.665Z" }, + { url = "https://files.pythonhosted.org/packages/9c/01/93552f75e0d2a7dd115a45e59209c51e8d514daff02fc887d2623be06fe1/scipy-1.18.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:97b6cddaaee0a779ef6b5ca83c9604b27cc16b2b8fc22c142652df8793319fb8", size = 23054441, upload-time = "2026-06-19T14:59:53.564Z" }, + { url = "https://files.pythonhosted.org/packages/3c/23/21f5e703643d66f21faa6b4c73195bfcad70c55efcb4f1ab327cd7c4101a/scipy-1.18.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:52a96e21517c7292375c0e27dd796a811f03fcea5fd4d108fdfea8145dcf17ab", size = 33968720, upload-time = "2026-06-19T14:59:56.415Z" }, + { url = "https://files.pythonhosted.org/packages/dd/aa/1b939f6c67ed68635bb538e6752d3dacc02f66535182e939a89581a44e9c/scipy-1.18.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f55797419e16e7f30cf88ffb3113ce0467f00cfe3f70d5c281730b21769bfc2", size = 35287115, upload-time = "2026-06-19T14:59:59.411Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ff/eec46be7e9234208f801062b53e1983085eddebd693f6c9bfb03b459830d/scipy-1.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ad033410e2e0672ffdc1042110cef20e1c46f8fd0616cee1d44d8d58fad8fc11", size = 35577989, upload-time = "2026-06-19T15:00:02.235Z" }, + { url = "https://files.pythonhosted.org/packages/84/ca/210d4759c7210bb7d269437421959b39a33434e2776b60c5cb8a763bb30a/scipy-1.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a55985d54c769c872e64b7f4c8a81cc30ef700cc04296abbbf3705439c126de", size = 37421717, upload-time = "2026-06-19T15:00:05.102Z" }, + { url = "https://files.pythonhosted.org/packages/2b/54/9a9edb45345bd6744da5ddfb6628e5d5185920494c6a67ec45b6381004cb/scipy-1.18.0-cp312-cp312-win_amd64.whl", hash = "sha256:71ccc8faa2dd16ac310233203474a8b5cb67f10dedd54a3116d34943f4b19132", size = 36597428, upload-time = "2026-06-19T15:00:08.112Z" }, + { url = "https://files.pythonhosted.org/packages/99/0e/33f32a2a58987e26aec0f7df252cbbad1e90ae77bdbc76f40dd4ed0cf0ea/scipy-1.18.0-cp312-cp312-win_arm64.whl", hash = "sha256:d88363fd9d8fbd3511bd273f1a49efb2a540773ddf92a91d57498ce7dd7f3e76", size = 24351481, upload-time = "2026-06-19T15:00:11.103Z" }, +] + [[package]] name = "six" version = "1.17.0"