- // ==UserScript==
- // @name 4399-flash-downloader
- // @namespace http://tampermonkey.net/
- // @version 0.0.1
- // @description 一键下载 flash 游戏(swf)
- // @author 2690874578@qq.com
- // @match https://www.4399.com/flash/*
- // @match https://s2.4399.com
- // @icon data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzMiIHZpZXdCb3g9IjAgMCAzMiAzMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiByeD0iMyIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzE3XzQpIi8+CjxnIGZpbHRlcj0idXJsKCNmaWx0ZXIwX2RfMTdfNCkiPgo8cGF0aCBkPSJNMyAzSDUuODIzMjNWNy41NDE3N0gxMS41MzU0VjNIMTQuMzU4NlYxNC45Nzk3SDExLjUzNTRWMTAuNDM4SDNWM1pNNS44ODg4OSAxOS45MTY1VjIxLjYyNzhIMTEuNjAxVjE5LjkxNjVINS44ODg4OVpNMjAuMzk5IDE5LjkxNjVWMjEuNjI3OEgyNi4xMTExVjE5LjkxNjVIMjAuMzk5Wk0xNy41NzU4IDE3LjAyMDNIMjlWMjlIMTcuNTc1OFYyNi4xNjk2SDI2LjExMTFWMjQuNDU4MkgxNy41NzU4VjE3LjAyMDNaTTMgMTcuMDIwM0gxNC40MjQyVjI5SDNWMjYuMTY5NkgxMS41MzU0VjI0LjQ1ODJIM1YxNy4wMjAzWk0xNy41NzU4IDNIMjlWMTQuOTc5N0gxNy41NzU4VjEyLjE0OTRIMjYuMTExMVYxMC40MzhIMTcuNTc1OFY3LjYwNzZIMjYuMTExMVY1Ljg5NjJIMTcuNTc1OFYzWiIgZmlsbD0id2hpdGUiLz4KPC9nPgo8ZGVmcz4KPGZpbHRlciBpZD0iZmlsdGVyMF9kXzE3XzQiIHg9IjIiIHk9IjMiIHdpZHRoPSIzMCIgaGVpZ2h0PSIzMCIgZmlsdGVyVW5pdHM9InVzZXJTcGFjZU9uVXNlIiBjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnM9InNSR0IiPgo8ZmVGbG9vZCBmbG9vZC1vcGFjaXR5PSIwIiByZXN1bHQ9IkJhY2tncm91bmRJbWFnZUZpeCIvPgo8ZmVDb2xvck1hdHJpeCBpbj0iU291cmNlQWxwaGEiIHR5cGU9Im1hdHJpeCIgdmFsdWVzPSIwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAxMjcgMCIgcmVzdWx0PSJoYXJkQWxwaGEiLz4KPGZlT2Zmc2V0IGR4PSIxIiBkeT0iMiIvPgo8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIxIi8+CjxmZUNvbXBvc2l0ZSBpbjI9ImhhcmRBbHBoYSIgb3BlcmF0b3I9Im91dCIvPgo8ZmVDb2xvck1hdHJpeCB0eXBlPSJtYXRyaXgiIHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMC40IDAiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbjI9IkJhY2tncm91bmRJbWFnZUZpeCIgcmVzdWx0PSJlZmZlY3QxX2Ryb3BTaGFkb3dfMTdfNCIvPgo8ZmVCbGVuZCBtb2RlPSJub3JtYWwiIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9ImVmZmVjdDFfZHJvcFNoYWRvd18xN180IiByZXN1bHQ9InNoYXBlIi8+CjwvZmlsdGVyPgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50MF9saW5lYXJfMTdfNCIgeDE9IjMxLjY4IiB5MT0iMzEuMDQiIHgyPSIzLjkxMDA2ZS0wNyIgeTI9Ii0xNy42IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiM1NkFGMEIiLz4KPHN0b3Agb2Zmc2V0PSIwLjk5MjcwOCIgc3RvcC1jb2xvcj0iIzUyQTUwRCIgc3RvcC1vcGFjaXR5PSIwIi8+CjwvbGluZWFyR3JhZGllbnQ+CjwvZGVmcz4KPC9zdmc+Cg==
- // @grant none
- // @run-at document-idle
- // @license GPL-3.0-only
- // ==/UserScript==
-
-
- (function() {
- /**
- * 脚本级全局常量
- */
-
- BASE_URL = "https://s2.4399.com/4399swf";
- FLASH_ICON = `data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzE0XzIpIj4KPHBhdGggZD0iTTI4LjI2NjcgMEgzLjczMzMzQzEuNzA2NjcgMCAwIDEuNzA2NjcgMCAzLjczMzMzVjI4LjI2NjdDMCAzMC4yOTMzIDEuNzA2NjcgMzIgMy43MzMzMyAzMkgyOC4yNjY3QzMwLjI5MzMgMzIgMzIgMzAuMjkzMyAzMiAyOC4yNjY3VjMuNzMzMzNDMzIgMS43MDY2NyAzMC4yOTMzIDAgMjguMjY2NyAwWk0yMy40NjY3IDEwLjEzMzNDMjMuNDY2NyAxMC40NTMzIDIzLjI1MzMgMTAuNjY2NyAyMi45MzMzIDEwLjY2NjdDMjAuMjY2NyAxMC42NjY3IDIwLjE2IDEwLjk4NjcgMTkuNzMzMyAxMi4xNkMxOS42MjY3IDEyLjM3MzMgMTkuNjI2NyAxMi41ODY3IDE5LjUyIDEyLjhIMjEuODY2N0MyMi4xODY3IDEyLjggMjIuNCAxMy4wMTMzIDIyLjQgMTMuMzMzM1YxNy42QzIyLjQgMTcuOTIgMjIuMTg2NyAxOC4xMzMzIDIxLjg2NjcgMTguMTMzM0gxOC4wMjY3QzE2Ljg1MzMgMjIuMjkzMyAxMi40OCAyNi42NjY3IDggMjYuNjY2N0M3LjY4IDI2LjY2NjcgNy40NjY2NyAyNi40NTMzIDcuNDY2NjcgMjYuMTMzM1YyMS44NjY3QzcuNDY2NjcgMjEuNTQ2NyA3LjY4IDIxLjMzMzMgOCAyMS4zMzMzQzExLjMwNjcgMjEuMzMzMyAxMi4yNjY3IDE4LjY2NjcgMTMuMzMzMyAxNS4yNTMzQzEzLjU0NjcgMTQuNzIgMTMuNjUzMyAxNC4yOTMzIDEzLjg2NjcgMTMuNzZDMTUuMjUzMyA5LjkyIDE2Ljg1MzMgNS4zMzMzMyAyMi45MzMzIDUuMzMzMzNDMjMuMjUzMyA1LjMzMzMzIDIzLjQ2NjcgNS41NDY2NyAyMy40NjY3IDUuODY2NjdWMTAuMTMzM1oiIGZpbGw9IiNEODFFMDYiLz4KPHBhdGggZD0iTTIxLjE3ODkgMzYuMDg0MkMxOS45MTU4IDM2LjA4NDIgMTguNjUyNiAzNS41Nzg5IDE3LjY0MjEgMzQuNTY4NEMxNS42MjEgMzIuNTQ3NCAxNS42MjEgMjkuMzg5NSAxNy42NDIxIDI3LjM2ODRMMjAuMjk0NyAyNC43MTU4TDIyLjA2MzIgMjYuNDg0MkwxOS40MTA1IDI5LjEzNjhDMTguNCAzMC4xNDc0IDE4LjQgMzEuNjYzMiAxOS40MTA1IDMyLjY3MzdDMjAuNDIxIDMzLjY4NDIgMjEuOTM2OCAzMy42ODQyIDIyLjk0NzQgMzIuNjczN0wyNi40ODQyIDI5LjEzNjhDMjYuOTg5NSAyOC42MzE2IDI3LjI0MjEgMjggMjcuMjQyMSAyNy4zNjg0QzI3LjI0MjEgMjYuNzM2OCAyNi45ODk1IDI2LjEwNTMgMjYuNjEwNSAyNS42TDI1LjIyMTEgMjQuMzM2OEwyNi45ODk1IDIyLjU2ODRMMjguMzc4OSAyMy45NTc5QzI5LjI2MzIgMjQuODQyMSAyOS43Njg0IDI2LjEwNTMgMjkuNzY4NCAyNy40OTQ3QzI5Ljc2ODQgMjguODg0MiAyOS4yNjMyIDMwLjE0NzQgMjguMjUyNiAzMS4wMzE2TDI0LjcxNTggMzQuNTY4NEMyMy44MzE2IDM1LjU3ODkgMjIuNDQyMSAzNi4wODQyIDIxLjE3ODkgMzYuMDg0MlpNMjUuMjIxMSAyOS42NDIxTDIzLjgzMTYgMjguMzc4OUMyMS44MTA1IDI2LjM1NzkgMjEuODEwNSAyMy4yIDIzLjgzMTYgMjEuMTc4OUwyNy4zNjg0IDE3LjY0MjFDMjkuMzg5NSAxNS42MjEgMzIuNTQ3NCAxNS42MjEgMzQuNTY4NCAxNy42NDIxQzM2LjU4OTUgMTkuNjYzMiAzNi41ODk1IDIyLjgyMSAzNC41Njg0IDI0Ljg0MjFMMzEuOTE1OCAyNy40OTQ3TDMwLjE0NzQgMjUuNzI2M0wzMi44IDIzLjA3MzdDMzMuODEwNSAyMi4wNjMyIDMzLjgxMDUgMjAuNTQ3NCAzMi44IDE5LjUzNjhDMzEuNzg5NSAxOC41MjYzIDMwLjE0NzQgMTguNTI2MyAyOS4yNjMyIDE5LjUzNjhMMjUuNiAyMi45NDc0QzI0LjU4OTUgMjMuOTU3OSAyNC41ODk1IDI1LjQ3MzcgMjUuNiAyNi40ODQyTDI2Ljk4OTUgMjcuODczN0wyNS4yMjExIDI5LjY0MjFaIiBmaWxsPSIjMjcyNjM2Ii8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDBfMTRfMiI+CjxyZWN0IHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPC9kZWZzPgo8L3N2Zz4K`;
-
-
- /**
- * 脚本级公用函数和对象
- */
-
- /**
- * 元素选择器
- * @param {string} selector 选择器
- * @returns {Array<HTMLElement>} 元素列表
- */
- function $(selector) {
- const self = this?.querySelectorAll ? this : document;
- return [...self.querySelectorAll(selector)];
- }
-
-
- /**
- * 安全元素选择器,直到元素存在时才返回元素列表,最多等待5秒
- * @param {string} selector 选择器
- * @returns {Promise<Array<HTMLElement>>} 元素列表
- */
- async function $$(selector) {
- const self = this?.querySelectorAll ? this : document;
-
- for (let i = 0; i < 10; i++) {
- let elems = [...self.querySelectorAll(selector)];
- if (elems.length > 0) {
- return elems;
- }
- await new Promise(r => setTimeout(r, 500));
- }
- throw Error(`"${selector}" not found`);
- }
-
-
- const util = {
- Socket: class Socket {
- /**
- * 创建套接字对象
- * @param {Window} target 目标窗口
- */
- constructor(target) {
- if (!(target.window && (target === target.window))) {
- console.log(target);
- throw new Error(`target is not a [Window Object]`);
- }
- this.target = target;
- this.connected = false;
- this.listeners = new Set();
- }
-
- get [Symbol.toStringTag]() { return "Socket"; }
-
- /**
- * 向目标窗口发消息
- * @param {*} message
- */
- talk(message) {
- if (!this.target) {
- throw new TypeError(
- `socket.target is not a window: ${this.target}`
- );
- }
- this.target.postMessage(message, "*");
- }
-
- /**
- * 添加捕获型监听器,返回实际添加的监听器
- * @param {Function} listener (e: MessageEvent) => {...}
- * @param {boolean} once 是否在执行后自动销毁,默认 false;如为 true 则使用自动包装过的监听器
- * @returns {Function} listener
- */
- listen(listener, once=false) {
- if (this.listeners.has(listener)) {
- return;
- }
-
- let real_listener = listener;
- // 包装监听器
- if (once) {
- const self = this;
- function wrapped(e) {
- listener(e);
- self.not_listen(wrapped);
- }
- real_listener = wrapped;
- }
-
- // 添加监听器
- this.listeners.add(real_listener);
- window.addEventListener(
- "message", real_listener, true
- );
- return real_listener;
- }
-
- /**
- * 移除socket上的捕获型监听器
- * @param {Function} listener (e: MessageEvent) => {...}
- */
- not_listen(listener) {
- console.log(listener);
- console.log(
- "listener delete operation:",
- this.listeners.delete(listener)
- );
- window.removeEventListener("message", listener, true);
- }
-
- /**
- * 检查对方来信是否为pong消息
- * @param {MessageEvent} e
- * @param {Function} resolve
- */
- _on_pong(e, resolve) {
- // 收到pong消息
- if (e.data.pong) {
- this.connected = true;
- this.listeners.forEach(
- listener => listener.ping ? this.not_listen(listener) : 0
- );
- console.log("Client: Connected!\n" + new Date());
- resolve(this);
- }
- }
-
- /**
- * 向对方发送ping消息
- * @returns {Promise<Socket>}
- */
- _ping() {
- return new Promise((resolve, reject) => {
- // 绑定pong检查监听器
- const listener = this.listen(
- e => this._on_pong(e, resolve)
- );
- listener.ping = true;
-
- // 5分钟后超时
- setTimeout(
- () => reject(new Error(`Timeout Error during receiving pong (>5min)`)),
- 5 * 60 * 1000
- );
- // 发送ping消息
- this.talk({ ping: true });
- });
- }
-
- /**
- * 检查对方来信是否为ping消息
- * @param {MessageEvent} e
- * @param {Function} resolve
- */
- _on_ping(e, resolve) {
- // 收到ping消息
- if (e.data.ping) {
- this.target = e.source;
- this.connected = true;
- this.listeners.forEach(
- listener => listener.pong ? this.not_listen(listener) : 0
- );
- console.log("Server: Connected!\n" + new Date());
-
- // resolve 后期约状态无法回退
- // 但后续代码仍可执行
- resolve(this);
- // 回应pong消息
- this.talk({ pong: true });
- }
- }
-
- /**
- * 当对方来信是为ping消息时回应pong消息
- * @returns {Promise<Socket>}
- */
- _pong() {
- return new Promise(resolve => {
- // 绑定ping检查监听器
- const listener = this.listen(
- e => this._on_ping(e, resolve)
- );
- listener.pong = true;
- });
- }
-
- /**
- * 连接至目标窗口
- * @param {boolean} talk_first 是否先发送ping消息
- * @param {Window} target 目标窗口
- * @returns {Promise<Socket>}
- */
- connect(talk_first) {
- // 先发起握手
- if (talk_first) {
- return this._ping();
- }
- // 后发起握手
- return this._pong();
- }
- },
-
- /**
- * 以指定原因弹窗提示并抛出错误
- * @param {string} reason
- */
- raise: function(reason) {
- alert(reason);
- throw new Error(reason);
- },
-
- /**
- * 返回一个包含计数器的迭代器, 其每次迭代值为 [index, value]
- * @param {Iterable} iterable
- * @returns
- */
- enumerate: function* (iterable) {
- let i = 0;
- for (let value of iterable) {
- yield [i++, value];
- }
- },
-
- /**
- * 同步的迭代若干可迭代对象
- * @param {...Iterable} iterables
- * @returns
- */
- zip: function* (...iterables) {
- // 强制转为迭代器
- const iterators = iterables.map(
- iterable => iterable[Symbol.iterator]()
- );
-
- // 逐次迭代
- while (true) {
- let [done, values] = base.getAllValus(iterators);
- if (done) {
- return;
- }
- if (values.length === 1) {
- yield values[0];
- } else {
- yield values;
- }
- }
- },
-
- /**
- * 返回指定范围整数生成器
- * @param {number} end 如果只提供 end, 则返回 [0, end)
- * @param {number} end2 如果同时提供 end2, 则返回 [end, end2)
- * @param {number} step 步长, 可以为负数,不能为 0
- * @returns
- */
- range: function*(end, end2=null, step=1) {
- // 参数合法性校验
- if (step === 0) {
- throw new RangeError("step can't be zero");
- }
- const len = end2 - end;
- if (end2 && len && step && (len * step < 0)) {
- throw new RangeError(`[${end}, ${end2}) with step ${step} is invalid`);
- }
-
- // 生成范围
- end2 = end2 === null ? 0 : end2;
- let [small, big] = [end, end2].sort((a, b) => a - b);
- // 开始迭代
- if (step > 0) {
- for (let i = small; i < big; i += step) {
- yield i;
- }
- } else {
- for (let i = big; i > small; i += step) {
- yield i;
- }
- };
- },
-
- /**
- * 复制text到剪贴板
- * @param {string} text
- * @returns
- */
- copy_text: function(text) {
- // 输出到控制台和剪贴板
- console.log(
- text.length > 20 ?
- text.slice(0, 21) + "..." : text
- );
-
- if (!navigator.clipboard) {
- base.oldCopy(text);
- return;
- };
-
- navigator.clipboard
- .writeText(text)
- .catch(_ => base.oldCopy(text));
- },
-
- /**
- * 复制媒体到剪贴板
- * @param {Blob} blob
- */
- copy: async function(blob) {
- const data = [new ClipboardItem({ [blob.type]: blob })];
- try {
- await navigator.clipboard.write(data);
- console.log(`${blob.type} 成功复制到剪贴板`);
- } catch (err) {
- console.error(err.name, err.message);
- }
- },
-
- /**
- * 创建并下载文件
- * @param {string} file_name 文件名
- * @param {ArrayBuffer | ArrayBufferView | Blob | string} content 内容
- * @param {string} type 媒体类型,需要符合 MIME 标准
- */
- save: function(file_name, content, type="") {
- const blob = new Blob(
- [content], { type }
- );
- const size = (blob.size / 1024).toFixed(1);
- console.log(`blob saved, size: ${size} kb, type: ${blob.type}`);
-
- const url = URL.createObjectURL(blob);
- const a = document.createElement("a");
- a.download = file_name || "未命名文件";
- a.href = url;
- a.click();
- URL.revokeObjectURL(url);
- },
-
- sleep: async function(delay_ms) {
- return new Promise(
- resolve => setTimeout(resolve, delay_ms)
- );
- },
-
- /**
- * 取得get参数key对应的value
- * @param {string} key
- * @returns {string} value
- */
- get_param: function(key) {
- return new URL(location.href).searchParams.get(key);
- },
-
- /**
- * 等待直到函数返回true
- * @param {Function} is_ok 判断条件达成与否的函数
- * @param {number} timeout 最大等待秒数, 默认5000毫秒
- */
- wait_until: async function(is_ok, timeout=5000) {
- const gap = 200;
- let chances = parseInt(timeout / gap);
- chances = chances < 1 ? 1 : chances;
-
- while (! await is_ok()) {
- await this.sleep(200);
- chances -= 1;
- if (!chances) {
- break;
- }
- }
- },
-
- /**
- * 用try移除元素
- * @param {HTMLElement} element 要移除的元素
- */
- remove: function(element) {
- try {
- element.remove();
- } catch (e) {}
- },
-
- /**
- * 等待全部任务落定后返回值的列表
- * @param {Iterable<Promise>} tasks
- * @returns {Promise<Array>} values
- */
- gather: async function(tasks) {
- const results = await Promise.allSettled(tasks);
- return results
- .filter(result => result.value)
- .map(result => result.value);
- },
-
- /**
- * 使用xhr异步GET请求目标url,返回响应体blob
- * @param {string} url
- * @returns {Promise<Blob>} blob
- */
- xhr_get_blob: async function(url) {
- const xhr = new XMLHttpRequest();
- xhr.open("GET", url);
- xhr.responseType = "blob";
-
- return new Promise((resolve, reject) => {
- xhr.onload = () => {
- const code = xhr.status;
- if (code >= 200 && code <= 299) {
- resolve(xhr.response);
- }
- else {
- reject(new Error(`Network Error: ${code}`));
- }
- }
- xhr.send();
- });
- },
-
- /**
- * 加载CDN脚本
- * @param {string} url
- */
- load_web_script: async function(url) {
- try {
- // xhr+eval方式
- Function(
- await (await this.xhr_get_blob(url)).text()
- )();
- } catch(e) {
- console.error(e);
- // 嵌入<script>方式
- const script = document.createElement("script");
- script.src = url;
- document.body.append(script);
- }
- },
- };
-
-
- /**
- * 域名级主函数
- */
-
-
- /**
- * 启动下载 flash 游戏文件
- */
- function dl_flash() {
- /**
- * 域名级全局变量
- */
-
- let sock;
-
-
- async function send_url() {
- const title = $(".name a")[0].textContent.trim() || "flash游戏";
- const path = window._strGamePath;
-
- if (!path) util.raise(
- "_strGamePath 不存在,找不到游戏文件路径"
- );
- if (!path.endsWith(".swf")) util.raise(
- `当前游戏不是 flash 游戏。\n游戏路径为:${path}`
- );
-
- const id = "flash-dl-src";
- let iframe = $(`#${id}`)[0];
-
- if (!iframe) {
- iframe = document.createElement("iframe");
- iframe.id = id;
- iframe.src = "https://s2.4399.com";
- document.body.append(iframe);
- sock = new util.Socket(iframe.contentWindow);
- await sock.connect(false);
- }
-
- sock.talk({
- flash_dl: true,
- url: BASE_URL + path,
- title,
- });
- }
-
- function add_style() {
- const style = `
- <style>
- #flash-dl-btn {
- text-align: center;
- background: url("${FLASH_ICON}");
- background-repeat: no-repeat;
- background-position: top;
- width: 40px;
- padding-top: 30px;
- margin: 0 10px;
- float: left;
- display: inline;
- cursor: pointer;
- }
-
- #flash-dl-src {
- display: none;
- }
- <style>
- `;
- document.head.insertAdjacentHTML(
- "beforeend", style
- );
- }
-
- async function add_dl_btn() {
- const box = (await $$("#uplayer .fr"))[0];
-
- // 修改误导性的下载按钮文本(下载4399游戏盒子)
- $("#down_a")[0].textContent = "盒子";
-
- // 新按钮
- const btn = document.createElement("a");
- btn.id = "flash-dl-btn";
- btn.textContent = "下载";
- btn.onfocus = () => btn.blur();
- btn.onclick = send_url;
- box.insertAdjacentElement("afterbegin", btn);
- }
-
- (() => {
- console.log("enter: dl_flash");
- add_style();
- add_dl_btn();
- })();
- }
-
- /**
- * 执行下载 flash 游戏文件
- */
- function dl_flash_in_origin() {
- /**
- * @param {MessageEvent} e
- */
- async function on_msg(e) {
- if (!e.data.flash_dl) return;
-
- const { url, title } = e.data;
- const resp = await fetch(url, {
- headers: {
- "Host": "szhong.4399.com",
- "X-Requested-With": "ShockwaveFlash/34.0.0.282",
- }
- });
- if (!resp.ok) util.raise(
- `游戏下载失败,错误代码:${resp.status},原因:${resp.statusText}`
- );
-
- const blob = await resp.blob();
- util.save(title, blob, "application/x-shockwave-flash");
- }
-
- (() => {
- console.log("enter: dl_flash_in_origin")
- if (window.top === window) return;
-
- const sock = new util.Socket(window.top);
- sock.listen(on_msg);
- sock.connect(true);
- })();
- }
-
-
- /**
- * 路由函数,脚本主函数入口
- */
- function route() {
- console.log("enter: route");
-
- const host = location.hostname;
- switch (host) {
- case "www.4399.com":
- dl_flash();
- break;
-
- case "s2.4399.com":
- dl_flash_in_origin();
- break;
-
- default:
- console.log(`不受支持的域名:${host}`);
- break;
- }
- }
-
-
- setTimeout(route, 500);
-
- /**
- * 更新日志
- * ---
- * 更新日期:2023/4/28
- * - 完成第一版 4399 flash 文件下载脚本
- */
- })();