Bilibili Live Tasks Helper

Enhancing the experience of watching Bilibili live streaming.

Tính đến 05-08-2023. Xem phiên bản mới nhất.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

Bạn sẽ cần cài đặt một tiện ích mở rộng như Tampermonkey hoặc Violentmonkey để cài đặt kịch bản này.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(Tôi đã có Trình quản lý tập lệnh người dùng, hãy cài đặt nó!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name            Bilibili Live Tasks Helper
// @name:en         Bilibili Live Tasks Helper
// @name:zh         Bilibili Live Tasks Helper
// @namespace       https://github.com/andywang425
// @version         7.0.4
// @author          andywang425
// @description     Enhancing the experience of watching Bilibili live streaming.
// @description:en  Enhancing the experience of watching Bilibili live streaming.
// @description:zh  Enhancing the experience of watching Bilibili live streaming.
// @license         MIT
// @copyright       2023, andywang425 (https://github.com/andywang425)
// @icon            data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNDEuMDY1IiBoZWlnaHQ9IjEyNy43NDciIHZpZXdCb3g9IjAgMCAzNy4zMjQgMzMuOCI+PHBhdGggZmlsbD0iIzIwYjBlMyIgZD0iTTg2Ljk2MiAxMTIuMzMyYTIuNjYxIDIuNjYxIDAgMCAxIDIuMjYyIDAgNS41MzYgNS41MzYgMCAwIDEgMS4zODQgMS4wMTFsNS4zMjMgNC42NThoMy44MDVsNS4zMjMtNC42NThhNS41ODkgNS41ODkgMCAwIDEgMS4zODQtMS4wMTEgMi42NjEgMi42NjEgMCAwIDEgMy41NCAyLjIwOSAyLjY2MSAyLjY2MSAwIDAgMS0uNTg2IDEuNzgzIDE0Ljg3NyAxNC44NzcgMCAwIDEtMS4xNzEgMS4wNjUgNy42OTEgNy42OTEgMCAwIDEtLjc0NS42MTJoMy4zMjZhNS42NDIgNS42NDIgMCAwIDEgMy45MTIgMS43NTYgNS42NjkgNS42NjkgMCAwIDEgMS43ODQgMy45MTJ2MTUuMzAzYTEwLjc3OCAxMC43NzggMCAwIDEtLjEzNCAyLjMxNSA1LjkwOCA1LjkwOCAwIDAgMS0yLjY2IDMuNzI2IDUuNzIyIDUuNzIyIDAgMCAxLTMuMDYxLjg1Mkg4Ni4yMTdhMTEuMjg0IDExLjI4NCAwIDAgMS0yLjM5Ni0uMTMzIDUuODgyIDUuODgyIDAgMCAxLTMuNjcyLTIuNjYyIDUuNjk1IDUuNjk1IDAgMCAxLS45MDUtMy4wNnYtMTUuMTQzYTExLjkyMyAxMS45MjMgMCAwIDEgMC0yLjIwOSA1Ljg1NSA1Ljg1NSAwIDAgMSA1LjMyMy00LjczN2gzLjQ4NmMtLjU1OS0uNC0xLjAzOC0uODc4LTEuNTQ0LTEuMzA0YTIuNjYxIDIuNjYxIDAgMCAxLS44NTEtMi4xODMgMi42NjEgMi42NjEgMCAwIDEgMS4zMDQtMi4xMDJtLS42MTIgMTAuMzI2YTIuNjYxIDIuNjYxIDAgMCAwLTIuMTAzIDEuOTE2IDMuNTkzIDMuNTkzIDAgMCAwIDAgMS4wMTF2MTIuNTg4YTIuNjYxIDIuNjYxIDAgMCAwIDEuODM3IDIuNjYyIDMuNTEzIDMuNTEzIDAgMCAwIDEuMTQ0LjE4NmgyMS42MzdhMi42NjEgMi42NjEgMCAwIDAgMi41MjgtMS41NyAzLjcyNiAzLjcyNiAwIDAgMCAuMjY2LTEuNzU3di0xMS43MWE0LjQ3MSA0LjQ3MSAwIDAgMCAwLTEuMjc3IDIuNjYxIDIuNjYxIDAgMCAwLTEuNzMtMS44MSA0LjI4NSA0LjI4NSAwIDAgMC0xLjY1LS4yMzlIODcuNjAxYTguODg5IDguODg5IDAgMCAwLTEuMjUxIDB6bTAgMCIgc3R5bGU9InN0cm9rZS13aWR0aDouMDMzMDcyOSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTc5LjE5MyAtMTEyLjA4KSIvPjxwYXRoIGQ9Ik04OC45NyAxMjguNjM2Yy4zNjMuMzc3Ljc0NS43NDcgMS4wODggMS4xNDIuNTk3LjY4NyAxLjExOCAxLjE5NyAxLjY2NiAxLjgwOS0uMTI5LTEuMTE3IDEuMzA0LTEuMTk4LjA3NC0xLjc1Ny0uNDA4LjQxNy0uOTQxLjg4NC0xLjM2IDEuMjIzLS4zOTIuMzE2LS44NjMuNjctMS4yMzUuOTUyLTEuOTA3IDEuNDQzLjIyNiA0LjA1MyAyLjEzIDIuNjA3IDAgMCAyLTEuNTM1IDIuODA3LTIuMzAxLjQ0LS40MTcuNjgtLjk1Ni43Mi0xLjU5Mi4wNC0uNjU0LS41MzUtMS4yNC0uNzk0LTEuNDk4LS45Mi0uOTE0LTEuNzQzLTEuOTY4LTIuNTUtMi44MTItMS41NzUtMS44LTQuMTIuNDI4LTIuNTQ2IDIuMjI3ek0xMDYuOTc5IDEyOC42MzZjLS4zNjMuMzc3LS43NDUuNzQ3LTEuMDg4IDEuMTQyLS41OTcuNjg3LTEuMTE4IDEuMTk3LTEuNjY2IDEuODA5LjEyOS0xLjExNy0xLjMwNC0xLjE5OC0uMDc0LTEuNzU3LjQwOC40MTcuOTQxLjg4NCAxLjM2IDEuMjIzLjM5Mi4zMTYuODYzLjY3IDEuMjM1Ljk1MiAxLjkwNyAxLjQ0My0uMjI2IDQuMDUzLTIuMTMgMi42MDcgMCAwLTItMS41MzUtMi44MDctMi4zMDEtLjQ0LS40MTctLjY4LS45NTYtLjcyLTEuNTkyLS4wNC0uNjU0LjUzNS0xLjI0Ljc5NC0xLjQ5OC45Mi0uOTE0IDEuNzQzLTEuOTY4IDIuNTUtMi44MTIgMS41NzUtMS44IDQuMTIuNDI4IDIuNTQ2IDIuMjI3eiIgc3R5bGU9ImZpbGw6IzIwYjBlMztmaWxsLW9wYWNpdHk6MTtzdHJva2Utd2lkdGg6LjUyNDE1OTtzdHJva2UtZGFzaGFycmF5Om5vbmUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC03OS4xOTMgLTExMi4wOCkiLz48L3N2Zz4NCg==
// @homepageURL     https://github.com/andywang425/BLTH
// @supportURL      https://github.com/andywang425/BLTH/issues
// @include         /^https?:\/\/live\.bilibili\.com\/(blanc\/)?\d+\??.*$/
// @require         https://unpkg.com/[email protected]/dist/vue.global.prod.js
// @require         data:application/javascript,window.Vue%3DVue%2Cwindow.VueDemi%3DVue%3B
// @require         https://unpkg.com/[email protected]/dist/index.full.min.js
// @require         https://unpkg.com/@element-plus/[email protected]/dist/index.iife.min.js
// @require         https://unpkg.com/[email protected]/dist/pinia.iife.prod.js
// @require         https://unpkg.com/[email protected]/lodash.min.js
// @require         https://unpkg.com/[email protected]/dist/hotkeys.min.js
// @require         https://unpkg.com/[email protected]/build/global/luxon.min.js
// @require         https://unpkg.com/[email protected]/crypto-js.js
// @resource        element-plus/dist/index.css  https://unpkg.com/[email protected]/dist/index.css
// @connect         api.bilibili.com
// @connect         api.live.bilibili.com
// @connect         api.vc.bilibili.com
// @connect         passport.bilibili.com
// @connect         live.bilibili.com
// @connect         live-trace.bilibili.com
// @grant           GM_getResourceText
// @grant           GM_getValue
// @grant           GM_setValue
// @grant           GM_xmlhttpRequest
// @grant           unsafeWindow
// @run-at          document-end
// ==/UserScript==

(a=>{const e=document.createElement("style");e.dataset.source="vite-plugin-monkey",e.textContent=a,document.head.append(e)})(" .title[data-v-dda95e10]{padding-left:20px;align-items:center;display:flex}.header-big-text[data-v-dda95e10]{font-size:var(--big-text-size)}.header-small-text[data-v-dda95e10]{font-size:var(--small-text-size);padding-top:calc(var(--big-text-size) - var(--small-text-size));margin-left:10px;--small-text-size: 18px}.collapse-btn[data-v-dda95e10]{display:flex;justify-content:center;align-items:center;height:100%;float:left;cursor:pointer}.avatar-wrap[data-v-eac67691]{width:80px;height:80px}.avatar[data-v-eac67691]{display:flex;justify-content:center;align-items:center;border-radius:50%}.base[data-v-4aed17ff]{z-index:1003;position:absolute;background-color:#fff;border-bottom:1px solid #e3e5e7;border-left:1px solid #e3e5e7;border-right:1px solid #e3e5e7}.header[data-v-4aed17ff]{position:relative;box-sizing:border-box;width:100%;font-size:var(--big-text-size);align-items:center;display:flex;border-bottom:1px solid #e3e5e7;height:60px;--big-text-size: 25px}.aside[data-v-4aed17ff]{width:auto}.aside #aside-el-menu[data-v-4aed17ff]:not(.el-menu--collapse){width:150px}.main[data-v-4aed17ff]{--main-top-botton-padding: calc(var(--el-main-padding) * .625);padding-top:var(--main-top-botton-padding);padding-bottom:var(--main-top-botton-padding)}.fade-enter-active[data-v-4aed17ff],.fade-leave-active[data-v-4aed17ff]{transition:opacity .1s ease}.fade-enter-from[data-v-4aed17ff],.fade-leave-to[data-v-4aed17ff]{opacity:0}.info-icon[data-v-c1d8df5e]{font-size:var(--el-font-size-base);cursor:pointer}.status-icon[data-v-2f9d6050]{font-size:var(--el-font-size-base)}.blth_btn{background-color:#23ade5;font-size:small;margin-inline-start:5px;color:#fff;border-radius:4px;border:none;padding:5px;cursor:pointer;box-shadow:0 0 2px #00000075;line-height:10px;margin-left:15px}.blth_btn:hover{background-color:#1097cc}.blth_btn:hover:active{background-color:#0e86b6;position:relative;top:1px}.el-link-va-baseline{vertical-align:baseline} ");

(function (vue, pinia, _, luxon, CryptoJS, ElementPlusIconsVue, ElementPlus, hotkeys) {
  'use strict';

  function _interopNamespaceDefault(e) {
    const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
    if (e) {
      for (const k in e) {
        if (k !== 'default') {
          const d = Object.getOwnPropertyDescriptor(e, k);
          Object.defineProperty(n, k, d.get ? d : {
            enumerable: true,
            get: () => e[k]
          });
        }
      }
    }
    n.default = e;
    return Object.freeze(n);
  }

  const ElementPlusIconsVue__namespace = /*#__PURE__*/_interopNamespaceDefault(ElementPlusIconsVue);

  var __defProp = Object.defineProperty;
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  var __publicField = (obj, key, value) => {
    __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
    return value;
  };
  var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
  var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
  var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
  var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
  const defaultValues = {
    ui: {
      isCollapse: false,
      isShowPanel: true,
      activeMenuIndex: "MainSiteTasks"
    },
    modules: {
      DailyTasks: {
        MainSiteTasks: {
          login: {
            enabled: false,
            _lastCompleteTime: 0
          },
          watch: {
            enabled: false,
            _lastCompleteTime: 0
          },
          coin: {
            enabled: false,
            num: 1,
            _lastCompleteTime: 0
          },
          share: {
            enabled: false,
            _lastCompleteTime: 0
          }
        },
        LiveTasks: {
          sign: {
            enabled: false,
            _lastCompleteTime: 0
          },
          appUser: {
            enabled: false,
            _lastCompleteTime: 0
          },
          medalTasks: {
            danmu: {
              enabled: false,
              list: [
                "(⌒▽⌒)",
                "( ̄▽ ̄)",
                "(=・ω・=)",
                "(`・ω・´)",
                "(〜 ̄△ ̄)〜",
                "(・∀・)",
                "(°∀°)ノ",
                "╮( ̄▽ ̄)╭",
                "_(:3」∠)_",
                "(^・ω・^ )",
                "(● ̄(エ) ̄●)",
                "ε=ε=(ノ≧∇≦)ノ",
                "⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄",
                "←◡←",
                `(●'◡'●)ノ♥`
              ],
              _lastCompleteTime: 0
            },
            like: {
              enabled: false,
              _lastCompleteTime: 0
            },
            watch: {
              enabled: false,
              time: 70,
              _watchedSecondsToday: 0,
              _lastWatchTime: 0,
              _lastCompleteTime: 0
            },
            isWhiteList: false,
            roomidList: []
          }
        },
        OtherTasks: {
          groupSign: {
            enabled: false,
            _lastCompleteTime: 0
          },
          silverToCoin: {
            enabled: false,
            _lastCompleteTime: 0
          },
          coinToSilver: {
            enabled: false,
            num: 1,
            _lastCompleteTime: 0
          }
        }
      },
      EnhanceExperience: {
        switchLiveStreamQuality: {
          enabled: false,
          qualityDesc: "原画"
        },
        banp2p: {
          enabled: false
        }
      }
    },
    cache: {
      lastAliveHeartBeatTime: 0
    }
  };
  class Storage {
    /**
     * 递归合并配置项。删除当前配置中不存在于默认配置的键,补上相对于默认配置缺少的键值,其它键值不变。
     *
     * 该方法会修改当前配置。
     *
     * @param current_config_item 当前配置
     * @param default_config_item 默认配置
     * @returns 修改后的当前配置
     * @example
     *
     * const current_config = { enabled: true, details: { type: 'efg', status: 'ok' }, msg: 'hi' };
     * const default_config = { enabled: false, details: { type: 'abc', num = 1 } };
     *
     * mergeConfig(current_config, default_config);
     * // => { enabled: true, details: { type: 'efg', num = 1 } }
     */
    static mergeConfigs(current_config_item, default_config_item) {
      const keysOnlyInCurrentConfigItem = _.difference(
        _.keys(current_config_item),
        _.keys(default_config_item)
      );
      current_config_item = _.omit(current_config_item, keysOnlyInCurrentConfigItem);
      const keysOnlyInDefaultItem = _.difference(
        _.keys(default_config_item),
        _.keys(current_config_item)
      );
      _.assign(current_config_item, _.pick(default_config_item, keysOnlyInDefaultItem));
      for (const [key, value] of Object.entries(current_config_item).filter(
        (keyValue) => !keysOnlyInDefaultItem.includes(keyValue[0])
      )) {
        if (_.isPlainObject(value)) {
          current_config_item[key] = this.mergeConfigs(value, default_config_item[key]);
        }
      }
      return current_config_item;
    }
    static setUiConfig(uiConfig) {
      _GM_setValue("ui", uiConfig);
    }
    static getUiConfig() {
      return this.mergeConfigs(_GM_getValue("ui", {}), defaultValues.ui);
    }
    static setModuleConfig(moduleConfig) {
      _GM_setValue("modules", moduleConfig);
    }
    static getModuleConfig() {
      return this.mergeConfigs(_GM_getValue("modules", {}), defaultValues.modules);
    }
    static setCache(cache) {
      _GM_setValue("cache", cache);
    }
    static getCache() {
      return this.mergeConfigs(_GM_getValue("cache", {}), defaultValues.cache);
    }
  }
  const useUIStore = pinia.defineStore("ui", () => {
    const uiConfig = vue.reactive(Storage.getUiConfig());
    const activeMenuName = vue.computed(() => {
      const index2name = {
        MainSiteTasks: "主站任务",
        LiveTasks: "直播任务",
        OtherTasks: "其它任务"
      };
      return index2name[uiConfig.activeMenuIndex];
    });
    const baseStyleValue = vue.reactive({
      top: 0,
      left: 0,
      height: 0,
      width: 0
    });
    const baseStyle = vue.computed(() => ({
      top: baseStyleValue.top.toString() + "px",
      left: baseStyleValue.left.toString() + "px",
      height: baseStyleValue.height.toString() + "px",
      width: baseStyleValue.width.toString() + "px"
    }));
    const isShowPanelButtonText = vue.computed(() => {
      if (uiConfig.isShowPanel) {
        return "隐藏控制面板";
      } else {
        return "显示控制面板";
      }
    });
    const scrollBarHeight = vue.computed(() => (baseStyleValue.height - 60).toString() + "px");
    function changeCollapse() {
      uiConfig.isCollapse = !uiConfig.isCollapse;
    }
    function changeShowPanel() {
      uiConfig.isShowPanel = !uiConfig.isShowPanel;
    }
    function setActiveMenuIndex(index) {
      uiConfig.activeMenuIndex = index;
    }
    vue.watch(
      uiConfig,
      _.debounce((newUiConfig) => Storage.setUiConfig(newUiConfig), 350)
    );
    return {
      isShowPanelButtonText,
      activeMenuName,
      baseStyleValue,
      baseStyle,
      scrollBarHeight,
      uiConfig,
      changeCollapse,
      changeShowPanel,
      setActiveMenuIndex
    };
  });
  const useBiliStore = pinia.defineStore("bili", () => {
    const BilibiliLive = vue.ref();
    const cookies = vue.ref();
    const userInfo = vue.ref();
    const giftConfig = vue.ref();
    const dailyRewardInfo = vue.ref();
    const dynamicVideos = vue.ref();
    const fansMedals = vue.ref();
    const filteredFansMedals = vue.computed(() => {
      if (!fansMedals.value)
        return null;
      return fansMedals.value.filter((m) => m.room_info.room_id !== 0);
    });
    return {
      BilibiliLive,
      userInfo,
      giftConfig,
      cookies,
      dailyRewardInfo,
      dynamicVideos,
      fansMedals,
      filteredFansMedals
    };
  });
  class Request {
    constructor(url_prefix, orgin) {
      /** 请求 URL 的前缀 */
      __publicField(this, "url_prefix");
      /**
       * 请求 Header 中 Origin 的值,为了方便同时也是 Referer 的值
       */
      __publicField(this, "origin");
      this.url_prefix = url_prefix ?? "";
      this.origin = orgin ?? "https://bilibili.com";
    }
    /**
     * 发起一个 GET 请求
     * @param url 请求 URL 除去前缀的部分
     * @param params URL 参数
     * @param otherDetails GM_xmlhttpRequest 的 details 参数
     * @returns Promise
     */
    get(url, params, otherDetails) {
      return new Promise((resolve, reject) => {
        const defaultDetails = {
          method: "GET",
          url: this.url_prefix + url + (params ? "?" + new URLSearchParams(params).toString() : ""),
          responseType: "json",
          headers: {
            Accept: "application/json, text/plain, */*",
            Referer: this.origin,
            Origin: this.origin,
            "Sec-Fetch-Site": "same-site"
          },
          onload: function(response) {
            resolve(response.response);
          },
          onerror: function(err) {
            reject(err);
          }
        };
        const details = _.defaultsDeep(otherDetails, defaultDetails);
        _GM_xmlhttpRequest(details);
      });
    }
    /**
     * 发起一个 POST 请求
     * @param url 请求 URL 除去前缀的部分
     * @param data application/x-www-form-urlencoded 其它类型的数据需要在 otherDetails 中定义
     * @param otherDetails GM_xmlhttpRequest 的 details 参数
     * @returns Promise
     */
    post(url, data, otherDetails) {
      return new Promise((resolve, reject) => {
        const defaultDetails = {
          method: "POST",
          url: this.url_prefix.concat(url),
          data: new URLSearchParams(data).toString(),
          responseType: "json",
          headers: {
            Accept: "application/json, text/plain, */*",
            Referer: this.origin,
            Origin: this.origin,
            "Sec-Fetch-Site": "same-site",
            "Content-Type": "application/x-www-form-urlencoded"
          },
          onload: function(response) {
            resolve(response.response);
          },
          onerror: function(err) {
            reject(err);
          }
        };
        const details = _.defaultsDeep(otherDetails, defaultDetails);
        if (details.headers["Content-Type"] === "multipart/form-data") {
          delete details.headers["Content-Type"];
        }
        _GM_xmlhttpRequest(details);
      });
    }
  }
  function uuid() {
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
      const randomInt = 16 * Math.random() | 0;
      return ("x" === char ? randomInt : 3 & randomInt | 8).toString(16);
    });
  }
  function sleep(miliseconds) {
    return new Promise((resolve) => setTimeout(resolve, miliseconds));
  }
  function wait(type, timeout = -1) {
    return new Promise((resolve) => {
      useModuleStore().emitter.on(type, (event) => resolve(event));
      if (timeout !== -1)
        setTimeout(resolve, timeout);
    });
  }
  function packFormData(json) {
    const formData = new FormData();
    _.forEach(json, (value, key) => formData.append(key, value.toString()));
    return formData;
  }
  function deepestIterate(obj, fn, path) {
    _.forOwn(obj, function(value, key) {
      const newPath = path ? path + "." + key : key;
      if (_.isPlainObject(value) && !_.isEmpty(value)) {
        deepestIterate(value, fn, newPath);
      } else {
        fn(value, newPath);
      }
    });
  }
  luxon.Settings.defaultZone = "Asia/Shanghai";
  function isTimestampToday(timestamp, hour = 0, minute = 5) {
    const time = luxon.DateTime.fromMillis(timestamp);
    const startOfADay = luxon.DateTime.now().set({
      hour,
      minute,
      second: 0,
      millisecond: 0
    });
    const startOfTomorrow = startOfADay.plus({ days: 1 });
    const startOfYesterday = startOfADay.minus({ days: 1 });
    if (luxon.DateTime.now() >= startOfADay) {
      return time >= startOfADay && time < startOfTomorrow;
    } else {
      return time >= startOfYesterday && time < startOfADay;
    }
  }
  function delayToNextMoment(hour = 0, minute = 5) {
    const now = luxon.DateTime.now();
    let nextTime = luxon.DateTime.local(now.year, now.month, now.day, hour, minute);
    if (now > nextTime) {
      nextTime = nextTime.plus({ days: 1 });
    }
    const diff = nextTime.diff(now);
    return {
      // 时间戳
      ms: diff.toMillis(),
      // 便于阅读的字符串,去掉开头的0小时和0分钟
      str: diff.toFormat("h小时m分钟s秒").replace(/^0小时/, "").replace(/^0分钟/, "")
    };
  }
  function isNowIn(startHour, startMinute, endHour, endMinute) {
    const now = luxon.DateTime.now();
    const start = luxon.DateTime.local(now.year, now.month, now.day, startHour, startMinute);
    const end = luxon.DateTime.local(now.year, now.month, now.day, endHour, endMinute);
    return now >= start && now < end;
  }
  function ts() {
    return Math.round(luxon.DateTime.now().toSeconds());
  }
  function tsm() {
    return luxon.DateTime.now().toMillis();
  }
  const request = {
    live: new Request("https://api.live.bilibili.com", "https://live.bilibili.com"),
    liveTrace: new Request("https://live-trace.bilibili.com", "https://live.bilibili.com"),
    passport: new Request("https://passport.bilibili.com", "https://passport.bilibili.com/"),
    main: new Request("https://api.bilibili.com", "https://www.bilibili.com"),
    vc: new Request("https://api.vc.bilibili.com", "https://message.bilibili.com/"),
    raw: new Request()
  };
  const BAPI = {
    live: {
      roomGiftConfig: (room_id = 0, area_parent_id = 0, area_id = 0, platform = "pc") => {
        return request.live.get("/xlive/web-room/v1/giftPanel/roomGiftConfig", {
          platform,
          room_id,
          area_parent_id,
          area_id
        });
      },
      doSign: () => {
        return request.live.get("/xlive/web-ucenter/v1/sign/DoSign");
      },
      getSignInfo: () => {
        return request.live.get("/xlive/web-ucenter/v1/sign/WebGetSignInfo");
      },
      fansMedalPanel: (page, page_size = 10) => {
        return request.live.get(
          "/xlive/app-ucenter/v1/fansMedal/panel",
          {
            page,
            page_size
          },
          {
            Origin: "https://link.bilibili.com",
            Referer: "https://link.bilibili.com/p/center/index"
          }
        );
      },
      sendMsg: (msg, roomid, room_type = 0, mode = 1, jumpfrom = 0, fontsize = 25, color = 16777215, bubble = 0) => {
        const biliStore = useBiliStore();
        const bili_jct = biliStore.cookies.bili_jct;
        return request.live.post("/msg/send", void 0, {
          data: packFormData({
            roomid,
            room_type,
            rnd: ts(),
            msg,
            mode,
            jumpfrom,
            fontsize,
            csrf: bili_jct,
            csrf_token: bili_jct,
            color,
            bubble
          }),
          headers: {
            "Content-Type": "multipart/form-data"
          }
        });
      },
      likeReport: (room_id, anchor_id) => {
        const biliStore = useBiliStore();
        const bili_jct = biliStore.cookies.bili_jct;
        return request.live.post("/xlive/app-ucenter/v1/like_info_v3/like/likeReportV3", {
          room_id,
          anchor_id,
          uid: anchor_id,
          ts: ts(),
          csrf: bili_jct
        });
      },
      /**
       * 该API只在带有多层iframe(背景很好看)的直播间中被使用,但参数填任意直播间均可
       */
      getInfoByRoom: (room_id) => {
        return request.live.get("/xlive/web-room/v1/index/getInfoByRoom", {
          room_id
        });
      },
      getUserTaskProgress: (target_id = 11153765) => {
        const biliStore = useBiliStore();
        const bili_jct = biliStore.cookies.bili_jct;
        return request.live.get("/xlive/app-ucenter/v1/userTask/GetUserTaskProgress", {
          target_id,
          csrf: bili_jct,
          ts: ts()
        });
      },
      userTaskReceiveRewards: (target_id = 11153765) => {
        const biliStore = useBiliStore();
        const bili_jct = biliStore.cookies.bili_jct;
        return request.live.post("/xlive/app-ucenter/v1/userTask/UserTaskReceiveRewards", {
          actionKey: "csrf",
          target_id,
          csrf: bili_jct,
          ts: ts()
        });
      },
      silver2coin: (visit_id = "") => {
        const bili_jct = useBiliStore().cookies.bili_jct;
        return request.live.post("/xlive/revenue/v1/wallet/silver2coin", {
          csrf: bili_jct,
          csrf_token: bili_jct,
          visit_id
        });
      },
      coin2silver: (num, platform = "pc", visit_id = "") => {
        const bili_jct = useBiliStore().cookies.bili_jct;
        return request.live.post("/xlive/revenue/v1/wallet/coin2silver", {
          num,
          csrf: bili_jct,
          csrf_token: bili_jct,
          platform,
          visit_id
        });
      }
    },
    liveTrace: {
      E: (id, device, ruid, is_patch = 0, heart_beat = [], visit_id = "") => {
        const bili_jct = useBiliStore().cookies.bili_jct;
        return request.liveTrace.post("/xlive/data-interface/v1/x25Kn/E", {
          id: JSON.stringify(id),
          device: JSON.stringify(device),
          ruid,
          // 主播 uid
          ts: tsm(),
          is_patch,
          heart_beat: JSON.stringify(heart_beat),
          ua: navigator.userAgent,
          csrf_token: bili_jct,
          csrf: bili_jct,
          visit_id
        });
      },
      X: (s, id, device, ruid, ets, benchmark, time, ts2, visit_id = "") => {
        const bili_jct = useBiliStore().cookies.bili_jct;
        return request.liveTrace.post("/xlive/data-interface/v1/x25Kn/X", {
          s,
          id: JSON.stringify(id),
          device: JSON.stringify(device),
          ruid,
          // 主播 uid
          ets,
          benchmark,
          time,
          ts: ts2,
          ua: navigator.userAgent,
          csrf_token: bili_jct,
          csrf: bili_jct,
          visit_id
        });
      }
    },
    main: {
      nav: () => {
        return request.main.get("/x/web-interface/nav");
      },
      reward: () => {
        return request.main.get("/x/member/web/exp/reward");
      },
      dynamicAll: (type, page = 1, timezone_offset = -480, features = "itemOpusStyle") => {
        return request.main.get("/x/polymer/web-dynamic/v1/feed/all", {
          timezone_offset,
          type,
          page,
          features
        });
      },
      videoHeartbeat: (aid, cid = "", realtime = 0, played_time = 0, real_played_time = 0, refer_url = "https://t.bilibili.com/?spm_id_from=444.3.0.0", quality = 116, video_duration = 100, type = 3, sub_type = 0, play_type = 0, dt = 2, last_play_progress_time = 0, max_play_progress_time = 0, spmid = "333.488.0.0", from_spmid = "333.31.list.card_archive.click", extra = '{"player_version":"4.1.21-rc.1727.0"}') => {
        const biliStore = useBiliStore();
        return request.main.post("/x/click-interface/web/heartbeat", {
          start_ts: ts(),
          mid: useBiliStore().BilibiliLive.UID,
          aid,
          cid,
          type,
          sub_type,
          dt,
          play_type,
          realtime,
          played_time,
          real_played_time,
          refer_url,
          quality,
          video_duration,
          last_play_progress_time,
          max_play_progress_time,
          spmid,
          from_spmid,
          extra,
          csrf: biliStore.cookies.bili_jct
        });
      },
      share: (aid, source = "pc_client_normal", eab_x = 2, ramval = 0, ga = 1) => {
        const bili_jct = useBiliStore().cookies.bili_jct;
        return request.main.post("/x/web-interface/share/add", {
          aid,
          eab_x,
          ramval,
          source,
          ga,
          csrf: bili_jct
        });
      },
      coinAdd: (aid, num, select_like = 0, cross_domain = true, eab_x = 2, ramval = 6, source = "web_normal", ga = 1) => {
        const bili_jct = useBiliStore().cookies.bili_jct;
        return request.main.post("/x/web-interface/coin/add ", {
          aid,
          multiply: num,
          select_like,
          cross_domain,
          eab_x,
          ramval,
          source,
          ga,
          csrf: bili_jct
        });
      },
      videoRelation: (aid, bvid = "") => {
        return request.main.get("/x/web-interface/archive/relation", {
          aid,
          bvid
        });
      }
    },
    vc: {
      myGroups: (build = 0, mobi_app = "web") => {
        return request.vc.get("/link_group/v1/member/my_groups", {
          build,
          mobi_app
        });
      },
      signIn: (group_id, owner_id) => {
        return request.vc.get("/link_setting/v1/link_setting/sign_in", {
          group_id,
          owner_id
        });
      }
    }
  };
  class Logger {
    constructor(title) {
      __publicField(this, "NAME", "BLTH");
      __publicField(this, "prefix_title_str");
      __publicField(this, "_title");
      this._title = title;
      this.prefix_title_str = title.split("_").join("][");
    }
    get prefix() {
      return [
        `%c${this.NAME}%c[${( new Date()).toLocaleString()}]%c[${this.prefix_title_str}]%c:`,
        "font-weight: bold; color: white; background-color: #23ade5; padding: 1px 4px; border-radius: 4px;",
        "font-weight: bold; color: #0920e6;",
        "font-weight: bold;",
        ""
      ];
    }
    log(...data) {
      console.log(...this.prefix, ...data);
    }
    error(...data) {
      console.error(...this.prefix, ...data);
    }
    warn(...data) {
      console.warn(...this.prefix, ...data);
    }
  }
  class BaseModule {
    constructor(moduleName) {
      /**
       * 模块名称,在被导出时定义
       *
       * 输出控制台日志时会用到
       */
      __publicField(this, "moduleName");
      /**
       * 用于在控制台中输出日志信息
       */
      __publicField(this, "logger");
      /**
       * 储存所有模块信息的 Pinia Store
       */
      __publicField(this, "moduleStore", useModuleStore());
      /**
       * 推荐添加一个 config 属性来表示当前模块的配置项
       *
       * @example this.moduleStore.moduleConfig.DailyTasks.MainSiteTasks.login
       */
      __publicField(this, "config");
      this.moduleName = moduleName;
      this.logger = new Logger(this.moduleName);
    }
    /**
     * 如果需要在控制面板上显示模块状态,推荐添加一个 status setter 用来设置模块状态
     *
     * @example
     * public set status(s: Istatus) {
     *    this.moduleStore.moduleStatus.DailyTasks.MainSiteTasks.login = s
     * }
     */
    set status(_s) {
      throw new Error("Method not implemented.");
    }
    run() {
      throw new Error("Method not implemented.");
    }
  }
  /**
   * 当脚本在多个页面上运行的时候,该模块是否要在每个页面上运行
   *
   * 默认false,即只在Main BLTH运行的页面上运行
   */
  __publicField(BaseModule, "runMultiple", false);
  class DefaultBaseModule extends BaseModule {
    /**
     * 默认模块按顺序逐个运行,所以必须返回一个 Promise
     */
    run() {
      throw new Error("Method not implemented.");
    }
  }
  /**
   * 优先级,数字越小优先级越高
   */
  __publicField(DefaultBaseModule, "sequence");
  function getCookie(name) {
    const nameEqual = name + "=";
    for (const cookie of document.cookie.split("; ")) {
      if (cookie.startsWith(nameEqual)) {
        const value = cookie.substring(nameEqual.length);
        return decodeURIComponent(value);
      }
    }
    return null;
  }
  function getCookies(names) {
    const cookies = {};
    for (const name of names) {
      cookies[name] = null;
    }
    for (const cookie of document.cookie.split("; ")) {
      for (let i = 0; i < names.length; i++) {
        const name = names[i];
        const nameEqual = name + "=";
        if (cookie.startsWith(nameEqual)) {
          const value = cookie.substring(nameEqual.length);
          cookies[name] = decodeURIComponent(value);
          names.splice(i, 1);
          break;
        }
      }
      if (names.length === 0)
        break;
    }
    return cookies;
  }
  class BiliInfo extends DefaultBaseModule {
    getBilibiliLive() {
      this.logger.log("unsafeWindow.BilibiliLive", _unsafeWindow.BilibiliLive);
      return _unsafeWindow.BilibiliLive;
    }
    /**
     * 获取 Cookies
     *
     * bili_jct: 常作为参数 csrf 在请求中出现
     * LIVE_BUVID 不能在此处获取,还没生成
     */
    getCookies() {
      return getCookies(["bili_jct"]);
    }
    /**
     * 通过 BAPI.main.nav 获取用户基本信息
     */
    async getUserInfo() {
      try {
        const response = await BAPI.main.nav();
        this.logger.log("BAPI.main.nav response", response);
        if (response.code === 0) {
          return Promise.resolve(response.data);
        } else {
          this.logger.error("获取用户信息失败", response.message);
          return Promise.reject(response.message);
        }
      } catch (error) {
        this.logger.error("获取用户信息出错", error);
        return Promise.reject(error);
      }
    }
    /**
     * 获取礼物配置信息
     *
     * 如礼物id,名称,亲密度等等
     */
    async getGiftConfig() {
      try {
        throw new Error("送礼功能尚未完成,暂时不需要获取礼物配置信息,请忽略本报错 >︿<");
        const response = await BAPI.live.roomGiftConfig();
        this.logger.log("BAPI.live.roomGiftConfig response", response);
        if (response.code === 0) {
          return Promise.resolve(response.data);
        } else {
          this.logger.error("获取礼物配置信息失败", response.message);
          return Promise.reject(response.message);
        }
      } catch (error) {
        this.logger.error("获取礼物配置信息出错", error);
        return Promise.reject(error);
      }
    }
    /**
     * 获取今日主站每日任务的完成情况
     */
    async getDailyRewardInfo() {
      const MainSiteTasks = this.moduleStore.moduleConfig.DailyTasks.MainSiteTasks;
      if (Object.values(MainSiteTasks).some((t) => t.enabled && !isTimestampToday(t._lastCompleteTime))) {
        try {
          const response = await BAPI.main.reward();
          this.logger.log("BAPI.main.reward response", response);
          if (response.code === 0) {
            return Promise.resolve(response.data);
          } else {
            this.logger.error("获取主站每日任务完成情况失败", response.message);
            return Promise.reject(response.message);
          }
        } catch (error) {
          this.logger.error("获取主站每日任务完成情况出错", error);
          return Promise.reject(error);
        }
      } else {
        return Promise.reject();
      }
    }
    /**
     * 从动态中获取一页视频的信息
     *
     * 每日观看视频,每日分享视频,每日投币都会用到
     */
    async getDynamicVideo() {
      const MainSiteTasks = this.moduleStore.moduleConfig.DailyTasks.MainSiteTasks;
      if (Object.entries(MainSiteTasks).filter(([key]) => ["watch", "share", "coin"].includes(key)).some((keyValue) => keyValue[1].enabled && !isTimestampToday(keyValue[1]._lastCompleteTime))) {
        try {
          const response = await BAPI.main.dynamicAll("video");
          this.logger.log("BAPI.main.dynamicAll response", response);
          if (response.code === 0) {
            return Promise.resolve(response.data.items);
          } else {
            this.logger.error("获取主站每日任务完成情况失败", response.message);
            return Promise.reject(response.message);
          }
        } catch (error) {
          this.logger.error("获取主站每日任务完成情况出错", error);
          return Promise.reject(error);
        }
      } else {
        return Promise.reject();
      }
    }
    /**
     * 获取粉丝勋章
     *
     * @param pages 获取的页数
     * @param force 是否无视配置强制获取,默认fasle
     */
    async getFansMetals(pages = 10, force = false) {
      const medalTasks = this.moduleStore.moduleConfig.DailyTasks.LiveTasks.medalTasks;
      if (force || Object.entries(medalTasks).filter(([key]) => ["danmu", "like", "watch"].includes(key)).some(
        (keyValue) => keyValue[1].enabled && !isTimestampToday(keyValue[1]._lastCompleteTime)
      )) {
        const fansMetalList = [];
        let total_page = 1;
        try {
          const firstPageResponse = await BAPI.live.fansMedalPanel(1);
          this.logger.log("BAPI.live.fansMedalPanel(1) response", firstPageResponse);
          if (firstPageResponse.code === 0) {
            total_page = firstPageResponse.data.page_info.total_page;
            fansMetalList.push(...firstPageResponse.data.special_list, ...firstPageResponse.data.list);
          } else {
            this.logger.error("获取粉丝勋章列表第1页失败", firstPageResponse.message);
            return Promise.reject(firstPageResponse.message);
          }
          for (let page = 2; page <= Math.min(total_page, pages); page++) {
            const response = await BAPI.live.fansMedalPanel(page);
            this.logger.log(`BAPI.live.fansMedalPanel(${page}) response`, response);
            if (firstPageResponse.code === 0) {
              fansMetalList.push(...response.data.list);
            } else {
              this.logger.error(`获取粉丝勋章列表第${page}页失败`, firstPageResponse.message);
              return fansMetalList;
            }
            await sleep(250);
          }
          return Promise.resolve(fansMetalList);
        } catch (error) {
          return Promise.reject(error);
        }
      } else {
        return Promise.reject();
      }
    }
    async run() {
      const biliStore = useBiliStore();
      biliStore.BilibiliLive = this.getBilibiliLive();
      biliStore.cookies = this.getCookies();
      biliStore.userInfo = await this.getUserInfo();
      setTimeout(async () => {
        biliStore.userInfo = await this.getUserInfo();
      }, delayToNextMoment(0, 4).ms);
      const allPromiseResult = await Promise.allSettled([
        this.getGiftConfig(),
        this.getDailyRewardInfo(),
        this.getDynamicVideo(),
        this.getFansMetals()
      ]);
      this.logger.log("allPromiseResult", allPromiseResult);
      biliStore.giftConfig = allPromiseResult[0].status === "fulfilled" ? allPromiseResult[0].value : null;
      biliStore.dailyRewardInfo = allPromiseResult[1].status === "fulfilled" ? allPromiseResult[1].value : null;
      setTimeout(async () => {
        const biliStore2 = useBiliStore();
        if (biliStore2.dailyRewardInfo) {
          biliStore2.dailyRewardInfo.login = false;
          biliStore2.dailyRewardInfo.share = false;
          biliStore2.dailyRewardInfo.watch = false;
          biliStore2.dailyRewardInfo.coins = 0;
        }
        biliStore2.dailyRewardInfo = await this.getDailyRewardInfo();
      }, delayToNextMoment(0, 4).ms);
      biliStore.dynamicVideos = allPromiseResult[2].status === "fulfilled" ? allPromiseResult[2].value : null;
      setTimeout(async () => {
        biliStore.dynamicVideos = await this.getDynamicVideo();
      }, delayToNextMoment(0, 4).ms);
      biliStore.fansMedals = allPromiseResult[3].status === "fulfilled" ? allPromiseResult[3].value : null;
      setTimeout(async () => {
        biliStore.fansMedals = await this.getFansMetals();
      }, delayToNextMoment(0, 4).ms);
      useModuleStore().emitter.on(this.moduleName, async (event) => {
        if (event.target === "getFansMetals") {
          biliStore.fansMedals = await this.getFansMetals(10, true);
        }
      });
    }
  }
  __publicField(BiliInfo, "sequence", 0);
  const defaultModules = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
    __proto__: null,
    BiliInfo
  }, Symbol.toStringTag, { value: "Module" }));
  class LoginTask extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "config", this.moduleStore.moduleConfig.DailyTasks.MainSiteTasks.login);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.MainSiteTasks.login = s;
    }
    async login() {
      this.logger.log("每日登录任务已完成");
      this.config._lastCompleteTime = tsm();
      this.status = "done";
      return Promise.resolve();
    }
    async run() {
      this.logger.log("每日登录模块开始运行");
      if (this.config.enabled) {
        const biliStore = useBiliStore();
        if (!isTimestampToday(this.config._lastCompleteTime)) {
          this.status = "running";
          if (biliStore.dailyRewardInfo && !biliStore.dailyRewardInfo.login) {
            await this.login();
          } else {
            this.config._lastCompleteTime = tsm();
            this.status = "done";
          }
        } else {
          if (!isNowIn(0, 0, 0, 5)) {
            this.logger.log("今天已经完成过每日登录任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的每日登录任务已经完成过了,等到今天的00:05再执行");
          }
        }
      }
      const diff = delayToNextMoment();
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("距离每日登录模块下次运行时间:", diff.str);
    }
  }
  let WatchTask$1 = class WatchTask extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "config", this.moduleStore.moduleConfig.DailyTasks.MainSiteTasks.watch);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.MainSiteTasks.watch = s;
    }
    getAid() {
      const biliStore = useBiliStore();
      if (!_.isEmpty(biliStore.dynamicVideos)) {
        return biliStore.dynamicVideos[0].modules.module_dynamic.major.archive.aid;
      } else {
        return "2";
      }
    }
    async watch(aid) {
      try {
        const response = await BAPI.main.videoHeartbeat(aid);
        this.logger.log(`BAPI.main.videoHeartbeat(${aid}) response`, response);
        if (response.code === 0) {
          this.logger.log("每日观看视频任务已完成");
          this.config._lastCompleteTime = tsm();
          this.status = "done";
        } else {
          this.logger.error("发送观看视频心跳失败", response.message);
          this.status = "error";
        }
      } catch (err) {
        this.logger.error("执行每日观看视频任务出错", err);
        this.status = "error";
      }
    }
    async run() {
      this.logger.log("每日观看视频模块开始运行");
      if (this.config.enabled) {
        const biliStore = useBiliStore();
        if (!isTimestampToday(this.config._lastCompleteTime)) {
          this.status = "running";
          if (biliStore.dailyRewardInfo && !biliStore.dailyRewardInfo.watch) {
            const aid = this.getAid();
            await this.watch(aid);
          } else {
            this.config._lastCompleteTime = tsm();
            this.status = "done";
            this.logger.log("每日观看视频任务已完成");
          }
        } else {
          if (!isNowIn(0, 0, 0, 5)) {
            this.logger.log("今天已经完成过每日观看视频任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的每日观看视频任务已经完成过了,等到今天的00:05再执行");
          }
        }
      }
      const diff = delayToNextMoment();
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("距离每日观看视频模块下次运行时间:", diff.str);
    }
  };
  class ShareTask extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "config", this.moduleStore.moduleConfig.DailyTasks.MainSiteTasks.share);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.MainSiteTasks.share = s;
    }
    getAid() {
      const biliStore = useBiliStore();
      if (!_.isEmpty(biliStore.dynamicVideos)) {
        return biliStore.dynamicVideos[0].modules.module_dynamic.major.archive.aid;
      } else {
        return "2";
      }
    }
    async share(aid) {
      try {
        const response = await BAPI.main.share(aid);
        this.logger.log(`BAPI.main.share(${aid}) response`, response);
        if (response.code === 0 || response.code === 71e3) {
          this.logger.log("每日分享视频任务已完成");
          this.config._lastCompleteTime = tsm();
          this.status = "done";
        } else {
          this.logger.error("分享视频失败", response.message);
          this.status = "error";
        }
      } catch (err) {
        this.logger.error("执行每日分享视频任务出错", err);
        this.status = "error";
      }
    }
    async run() {
      this.logger.log("每日分享视频模块开始运行");
      if (this.config.enabled) {
        const biliStore = useBiliStore();
        if (!isTimestampToday(this.config._lastCompleteTime)) {
          this.status = "running";
          if (biliStore.dailyRewardInfo && !biliStore.dailyRewardInfo.share) {
            const aid = this.getAid();
            await this.share(aid);
          } else {
            this.config._lastCompleteTime = tsm();
            this.status = "done";
            this.logger.log("每日分享视频任务已完成");
          }
        } else {
          if (!isNowIn(0, 0, 0, 5)) {
            this.logger.log("今天已经完成过每日分享任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的每日分享任务已经完成过了,等到今天的00:05再执行");
          }
        }
      }
      const diff = delayToNextMoment();
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("距离每日分享视频模块下次运行时间:", diff.str);
    }
  }
  class CoinTask extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "config", this.moduleStore.moduleConfig.DailyTasks.MainSiteTasks.coin);
      // 暂时先限制每个视频最多投一个币
      // 因为转载视频只能投一个币,原创视频能投两个币
      // 但是想查询视频是否为转载,我目前只知道一个 /x/web-interface/wbi/view
      // 通过其响应的copyright字段(1原创,2转载)来判断
      // 不过这个接口带有 wbi 签名,实现起来复杂
      // 所以干脆直接限制每个视频最多投一个币,反正视频数量足够
      __publicField(this, "MAX_COIN", 1);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.MainSiteTasks.coin = s;
    }
    getDynamicVideoIds() {
      const biliStore = useBiliStore();
      if (!_.isEmpty(biliStore.dynamicVideos)) {
        return biliStore.dynamicVideos.map((item) => {
          const archive = item.modules.module_dynamic.major.archive;
          return {
            aid: archive.aid,
            bvid: archive.bvid
          };
        });
      } else {
        this.status = "error";
        return null;
      }
    }
    async getVideoCoinInfo(aid, bvid) {
      try {
        const response = await BAPI.main.videoRelation(aid, bvid);
        this.logger.log(`BAPI.main.videoRelation(${aid}, ${bvid}) response`, response);
        if (response.code === 0) {
          return response.data.coin;
        } else {
          this.logger.error(`获取视频投币信息失败 aid = ${aid} bvid = ${bvid}`, response.message);
          return 0;
        }
      } catch (error) {
        this.logger.error(`获取视频投币信息出错 aid = ${aid} bvid = ${bvid}`, error);
        return 0;
      }
    }
    async coinDynamicVideos(left_coin_num) {
      const ids = this.getDynamicVideoIds();
      if (ids) {
        for (const { aid, bvid } of ids) {
          const coined_num = await this.getVideoCoinInfo(aid, bvid);
          const allowed_coin_num = this.MAX_COIN - coined_num;
          if (allowed_coin_num > 0) {
            const coin_num = Math.min(allowed_coin_num, left_coin_num);
            const result = await this.coin(aid, coin_num);
            if (result === 0) {
              left_coin_num -= coin_num;
              if (left_coin_num === 0) {
                this.logger.log("每日投币任务已完成");
                this.config._lastCompleteTime = tsm();
                this.status = "done";
                break;
              }
            } else if (result === 1) {
              this.status = "error";
              break;
            }
          }
        }
      }
    }
    async coin(aid, num) {
      try {
        const response = await BAPI.main.coinAdd(aid, num);
        this.logger.log(`BAPI.main.coinAdd(${aid}) response`, response);
        if (response.code === 0) {
          this.logger.log(`投币成功 视频aid = ${aid} 投币数量num = ${num}`);
          return 0;
        } else if (response.code === -104) {
          this.logger.warn("硬币余额不足,每日投币任务终止");
          return 1;
        } else {
          this.logger.error(`投币失败 视频aid = ${aid} 投币数量num = ${num}`, response.message);
          return 2;
        }
      } catch (err) {
        this.logger.error(`投币出错 视频aid = ${aid} 投币数量num = ${num}`, err);
        return 3;
      }
    }
    async run() {
      this.logger.log("每日投币模块开始运行");
      if (this.config.enabled) {
        const biliStore = useBiliStore();
        if (!isTimestampToday(this.config._lastCompleteTime)) {
          this.status = "running";
          if (biliStore.dailyRewardInfo) {
            const total_coined_num = biliStore.dailyRewardInfo.coins / 10;
            if (total_coined_num < this.config.num) {
              const left_coin_num = this.config.num - total_coined_num;
              const biliStore2 = useBiliStore();
              const money = biliStore2.userInfo.money ?? 5;
              if (left_coin_num > money) {
                this.logger.log("硬币余额不足,不执行每日投币任务");
                this.status = "done";
              } else {
                await this.coinDynamicVideos(left_coin_num);
              }
            } else {
              this.config._lastCompleteTime = tsm();
              this.status = "done";
              this.logger.log("每日投币任务已完成");
            }
          }
        } else {
          if (!isNowIn(0, 0, 0, 5)) {
            this.logger.log("今天已经完成过每日投币任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的每日投币任务已经完成过了,等到今天的00:05再执行");
          }
        }
      }
      const diff = delayToNextMoment();
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("距离每日投币模块下次运行时间:", diff.str);
    }
  }
  const dq = document.querySelector.bind(document);
  document.querySelectorAll.bind(document);
  const dce = document.createElement.bind(document);
  const pollingQuery = (element, selectors, intervel, timeout) => {
    return new Promise((resolve, reject) => {
      const timerPolling = setInterval(() => {
        const ele = element.querySelector(selectors);
        if (ele) {
          clearTimeout(timerPolling);
          resolve(ele);
        }
      }, intervel);
      const timerTimeout = setTimeout(() => {
        clearTimeout(timerPolling);
        clearTimeout(timerTimeout);
        reject();
      }, timeout);
    });
  };
  const isTargetFrame = () => {
    if (_unsafeWindow.BilibiliLive) {
      return true;
    } else {
      return false;
    }
  };
  const isSelfTopFrame = () => _unsafeWindow.self === _unsafeWindow.top;
  const topFrameDocuemnt = () => {
    var _a;
    return (_a = _unsafeWindow.top) == null ? void 0 : _a.document;
  };
  class SignTask extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "config", this.moduleStore.moduleConfig.DailyTasks.LiveTasks.sign);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.LiveTasks.sign = s;
    }
    async getSignInfo() {
      try {
        const response = await BAPI.live.getSignInfo();
        this.logger.log("BAPI.live.getSignInfo response", response);
        if (response.code === 0) {
          return response.data;
        } else {
          this.logger.error("获取直播签到信息失败", response.message);
          return null;
        }
      } catch (error) {
        this.logger.error("获取直播签到信息出错", error);
        return null;
      }
    }
    async sign() {
      try {
        const response = await BAPI.live.doSign();
        this.logger.log(`BAPI.live.doSign response`, response);
        if (response.code === 0) {
          this.logger.log("直播签到成功,获得奖励:", response.data.text);
          this.config._lastCompleteTime = tsm();
          this.status = "done";
          this.logger.log("直播签到任务已完成");
          const checkinBtn = dq(".checkin-btn");
          if (checkinBtn) {
            checkinBtn.remove();
          }
        } else {
          this.logger.error("直播签到失败", response.message);
          this.status = "error";
        }
      } catch (err) {
        this.logger.error("执行直播签到任务出错", err);
        this.status = "error";
      }
    }
    async run() {
      this.logger.log("直播签到模块开始运行");
      if (this.config.enabled) {
        if (!isTimestampToday(this.config._lastCompleteTime)) {
          this.status = "running";
          const signInfo = await this.getSignInfo();
          if (signInfo) {
            if (signInfo.status === 0) {
              await this.sign();
            } else {
              this.config._lastCompleteTime = tsm();
              this.status = "done";
            }
          } else {
            await this.sign();
          }
        } else {
          if (!isNowIn(0, 0, 0, 5)) {
            this.logger.log("今天已经完成过直播签到任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的直播签到任务已经完成过了,等到今天的00:05再执行");
          }
        }
      }
      const diff = delayToNextMoment();
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("距离直播签到模块下次运行时间:", diff.str);
    }
  }
  class AppUserTask extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "config", this.moduleStore.moduleConfig.DailyTasks.LiveTasks.appUser);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.LiveTasks.appUser = s;
    }
    async getUserTaskProgress() {
      try {
        const response = await BAPI.live.getUserTaskProgress();
        this.logger.log("BAPI.live.getUserTaskProgress response", response);
        if (response.code === 0) {
          return response.data;
        } else {
          this.logger.error("获取APP用户任务进度失败", response.message);
          this.status = "error";
          return null;
        }
      } catch (error) {
        this.logger.error("获取APP用户任务进度出错", error);
        this.status = "error";
        return null;
      }
    }
    async userTaskReceiveRewards() {
      try {
        const response = await BAPI.live.userTaskReceiveRewards();
        this.logger.log("BAPI.live.userTaskReceiveRewards response", response);
        if (response.code === 0) {
          return response.data;
        } else {
          this.logger.error("获取APP用户任务进度失败", response.message);
          this.status = "error";
          return null;
        }
      } catch (error) {
        this.logger.error("获取APP用户任务进度出错", error);
        this.status = "error";
        return null;
      }
    }
    async sendDanmu(danmu, roomid) {
      try {
        const response = await BAPI.live.sendMsg(danmu, roomid);
        this.logger.log(`BAPI.live.sendMsg(${danmu}, ${roomid})`, response);
        if (response.code === 0) {
          this.logger.log(`在直播间 ${roomid} 发送弹幕 ${danmu} 成功`);
        } else {
          this.logger.error(`在直播间 ${roomid} 发送弹幕 ${danmu} 失败`, response.message);
        }
      } catch (error) {
        this.logger.error(`在直播间 ${roomid} 发送弹幕 ${danmu} 出错`, error);
      }
    }
    async run() {
      this.logger.log("APP用户任务模块开始运行");
      this.logger.warn("APP用户任务暂时没有,该模块不运行");
      this.config.enabled = false;
      if (this.config.enabled) {
        if (!isTimestampToday(this.config._lastCompleteTime)) {
          this.status = "running";
          const danmuConfig = this.moduleStore.moduleConfig.DailyTasks.LiveTasks.medalTasks.danmu;
          if (danmuConfig.enabled && !isTimestampToday(danmuConfig._lastCompleteTime)) {
            await wait(this.moduleName, 3e5);
          }
          const progressResponse = await this.getUserTaskProgress();
          if (progressResponse) {
            if (progressResponse.is_surplus !== -1) {
              if (progressResponse.day_task.status === 3) {
                this.config._lastCompleteTime = tsm();
                this.status = "done";
              } else if (progressResponse.day_task.status === 2) {
                const receiveResponse = await this.userTaskReceiveRewards();
                if (receiveResponse) {
                  const num = receiveResponse.num;
                  if (num) {
                    this.logger.log(`领取奖励成功:${num}个电池`);
                  } else {
                    this.logger.warn(`领取奖励失败:未领取到电池`);
                  }
                  this.config._lastCompleteTime = tsm();
                  this.status = "done";
                }
              } else {
                let remainProgress = progressResponse.day_task.target - progressResponse.day_task.progress;
                while (remainProgress > 0) {
                  await this.sendDanmu(`打卡${remainProgress}`, 22474988);
                  await sleep(2e3);
                  remainProgress--;
                }
                const receiveResponse = await this.userTaskReceiveRewards();
                if (receiveResponse) {
                  const num = receiveResponse.num;
                  if (num) {
                    this.logger.log(`领取奖励成功:${num}个电池`);
                  } else {
                    this.logger.warn(`领取奖励失败:未领取到电池`);
                  }
                  this.config._lastCompleteTime = tsm();
                  this.status = "done";
                }
              }
            } else {
              this.logger.log("今天APP用户任务的奖励已经没有了,明天早点来吧");
              this.config._lastCompleteTime = tsm();
              this.status = "done";
            }
          }
        } else {
          if (!isNowIn(0, 0, 0, 5)) {
            this.logger.log("今天已经完成过APP用户任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的APP用户任务已经完成过了,等到今天的00:05再执行");
          }
        }
      }
      const diff = delayToNextMoment();
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("距离APP用户任务模块下次运行时间:", diff.str);
    }
  }
  class LikeTask extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "medalTasksConfig", this.moduleStore.moduleConfig.DailyTasks.LiveTasks.medalTasks);
      __publicField(this, "config", this.medalTasksConfig.like);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.LiveTasks.medalTasks.like = s;
    }
    /**
     * 获取粉丝勋章的房间号和主播uid,过滤等级大于等于20或不符合黑白名单要求的粉丝勋章
     * @returns 数组,每个元素都是数组:[房间号,主播uid]
     */
    getRoomidUidList() {
      const biliStore = useBiliStore();
      if (biliStore.filteredFansMedals) {
        return biliStore.filteredFansMedals.filter(
          (medal) => medal.medal.level < 20 && (this.medalTasksConfig.isWhiteList ? this.medalTasksConfig.roomidList.includes(medal.room_info.room_id) : !this.medalTasksConfig.roomidList.includes(medal.room_info.room_id))
        ).map((medal) => [medal.room_info.room_id, medal.medal.target_id]).slice(0, 100);
      } else {
        this.status = "error";
        return null;
      }
    }
    async like(roomid, target_id) {
      try {
        const response = await BAPI.live.likeReport(roomid, target_id);
        this.logger.log(`BAPI.live.likeReport(${roomid}, ${target_id})`, response);
        if (response.code === 0) {
          this.logger.log(`给主播点赞 房间号 = ${roomid} 主播UID = ${target_id} 成功`);
        } else {
          this.logger.error(
            `给主播点赞 房间号 = ${roomid} 主播UID = ${target_id} 失败`,
            response.message
          );
        }
      } catch (error) {
        this.logger.error(`给主播点赞 房间号 = ${roomid} 主播UID = ${target_id} 出错`, error);
      }
    }
    async run() {
      this.logger.log("给主播点赞模块开始运行");
      if (this.config.enabled) {
        if (!isTimestampToday(this.config._lastCompleteTime)) {
          this.status = "running";
          const idList = this.getRoomidUidList();
          if (idList) {
            for (const [roomid, target_id] of idList) {
              await this.like(roomid, target_id);
              await sleep(2e3);
            }
            this.config._lastCompleteTime = tsm();
            this.status = "done";
            this.logger.log("给主播点赞任务已完成");
          }
        } else {
          if (!isNowIn(0, 0, 0, 5)) {
            this.logger.log("今天已经完成过给主播点赞任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的给主播点赞任务已经完成过了,等到今天的00:05再执行");
          }
        }
      }
      const diff = delayToNextMoment();
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("距离给主播点赞模块下次运行时间:", diff.str);
    }
  }
  class RoomHeart {
    constructor(roomID, areaID, parentID, ruid, watchedSeconds, isLast = false) {
      __publicField(this, "logger", new Logger("RoomHeart"));
      __publicField(this, "config");
      /** 是不是最后一个心跳任务 */
      __publicField(this, "isLast");
      /** 已观看时间(秒) */
      __publicField(this, "watchedSeconds");
      __publicField(this, "timer");
      __publicField(this, "stop", false);
      __publicField(this, "areaID");
      __publicField(this, "parentID");
      __publicField(this, "roomID");
      /** 主播的 UID */
      __publicField(this, "ruid");
      __publicField(this, "seq", 0);
      /** Cookie LIVE_BUVID */
      __publicField(this, "buvid", getCookie("LIVE_BUVID"));
      __publicField(this, "uuid", uuid());
      /** 计算签名和发送请求时均需要 JSON.stringify */
      __publicField(this, "device", [this.buvid, this.uuid]);
      /** 浏览器 user agent */
      __publicField(this, "ua", navigator.userAgent);
      __publicField(this, "heartBeatInterval");
      __publicField(this, "secretKey");
      __publicField(this, "secretRule");
      /** ets */
      __publicField(this, "timestamp");
      this.roomID = roomID;
      this.areaID = areaID;
      this.parentID = parentID;
      this.ruid = ruid;
      this.watchedSeconds = watchedSeconds;
      this.isLast = isLast;
      this.config = useModuleStore().moduleConfig.DailyTasks.LiveTasks.medalTasks.watch;
    }
    set status(s) {
      useModuleStore().moduleStatus.DailyTasks.LiveTasks.medalTasks.watch = s;
    }
    /** 计算签名和发送请求时均需要 JSON.stringify */
    get id() {
      return [this.parentID, this.areaID, this.seq, this.roomID];
    }
    /**
     * 开始心跳
     */
    start() {
      if (!this.buvid)
        return;
      this.timer = setTimeout(() => this.stop = true, delayToNextMoment(0, 0).ms);
      return this.E();
    }
    /**
     * E心跳,开始时发送一次
     */
    async E() {
      if (this.stop) {
        this.status = "";
        return;
      }
      try {
        const response = await BAPI.liveTrace.E(this.id, this.device, this.ruid);
        this.logger.log(
          `BAPI.liveTrace.E(${this.id}, ${this.device}, ${this.ruid}) response`,
          response
        );
        if (response.code === 0) {
          this.seq += 1;
          ({
            heartbeat_interval: this.heartBeatInterval,
            secret_key: this.secretKey,
            secret_rule: this.secretRule,
            timestamp: this.timestamp
          } = response.data);
          setTimeout(() => this.X(), this.heartBeatInterval * 1e3);
        } else {
          this.logger.error(
            `BAPI.liveTrace.E(${this.id}, ${this.device}, ${this.ruid}) 失败`,
            response.message
          );
        }
      } catch (error) {
        this.logger.error(`BAPI.liveTrace.E(${this.id}, ${this.device}, ${this.ruid}) 出错`, error);
      }
    }
    /**
     * X心跳,E心跳过后都是X心跳
     */
    async X() {
      if (this.stop) {
        this.status = "";
        return;
      }
      try {
        const sypderData = {
          id: JSON.stringify(this.id),
          device: JSON.stringify(this.device),
          ets: this.timestamp,
          benchmark: this.secretKey,
          time: this.heartBeatInterval,
          ts: tsm(),
          ua: this.ua
        };
        const s = this.sypder(JSON.stringify(sypderData), this.secretRule);
        const response = await BAPI.liveTrace.X(
          s,
          this.id,
          this.device,
          this.ruid,
          this.timestamp,
          this.secretKey,
          this.heartBeatInterval,
          sypderData.ts
        );
        this.logger.log(
          `BAPI.liveTrace.X(${s}, ${this.id}, ${this.device}, ${this.ruid}, ${this.timestamp}, ${this.secretKey}, ${this.heartBeatInterval}, ${sypderData.ts}) response`,
          response
        );
        if (response.code === 0) {
          this.seq += 1;
          this.watchedSeconds += this.heartBeatInterval;
          if (this.isLast) {
            this.config._watchedSecondsToday = this.watchedSeconds;
          }
          if (this.watchedSeconds >= this.config.time * 60) {
            if (this.isLast) {
              this.config._lastCompleteTime = tsm();
              this.logger.log("观看直播任务已完成");
              this.status = "done";
            }
            clearTimeout(this.timer);
            return;
          }
          ;
          ({
            heartbeat_interval: this.heartBeatInterval,
            secret_key: this.secretKey,
            secret_rule: this.secretRule,
            timestamp: this.timestamp
          } = response.data);
          setTimeout(() => this.X(), this.heartBeatInterval * 1e3);
        } else {
          this.logger.error(
            `BAPI.liveTrace.X(${s}, ${this.id}, ${this.device}, ${this.ruid}, ${this.timestamp}, ${this.secretKey}, ${this.heartBeatInterval}) 失败`,
            response.message
          );
        }
      } catch (error) {
        this.logger.error(
          `BAPI.liveTrace.X(s, ${this.id}, ${this.device}, ${this.ruid}, ${this.timestamp}, ${this.secretKey}, ${this.heartBeatInterval}) 出错`,
          error
        );
      }
    }
    /**
     * wasm 导出的 spyider 函数的 javascript 实现
     * @param str 一个经过 JSON.stringify 的 json 字符串
     * @param rule secret_rule 数组
     * @returns s
     */
    sypder(str, rule) {
      const data = JSON.parse(str);
      const [parent_id, area_id, seq_id, room_id] = JSON.parse(data.id);
      const [buvid, uuid2] = JSON.parse(data.device);
      const key = data.benchmark;
      const newData = {
        platform: "web",
        parent_id,
        area_id,
        seq_id,
        room_id,
        buvid,
        uuid: uuid2,
        ets: data.ets,
        time: data.time,
        ts: data.ts
      };
      let s = JSON.stringify(newData);
      for (const r of rule) {
        switch (r) {
          case 0:
            s = CryptoJS.HmacMD5(s, key).toString(CryptoJS.enc.Hex);
            break;
          case 1:
            s = CryptoJS.HmacSHA1(s, key).toString(CryptoJS.enc.Hex);
            break;
          case 2:
            s = CryptoJS.HmacSHA256(s, key).toString(CryptoJS.enc.Hex);
            break;
          case 3:
            s = CryptoJS.HmacSHA224(s, key).toString(CryptoJS.enc.Hex);
            break;
          case 4:
            s = CryptoJS.HmacSHA512(s, key).toString(CryptoJS.enc.Hex);
            break;
          case 5:
            s = CryptoJS.HmacSHA384(s, key).toString(CryptoJS.enc.Hex);
            break;
          default:
            s = CryptoJS.HmacMD5(s, key).toString(CryptoJS.enc.Hex);
        }
      }
      return s;
    }
  }
  class WatchTask2 extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "medalTasksConfig", this.moduleStore.moduleConfig.DailyTasks.LiveTasks.medalTasks);
      __publicField(this, "config", this.medalTasksConfig.watch);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.LiveTasks.medalTasks.watch = s;
    }
    /**
     * 获取粉丝勋章的房间号和主播uid,过滤等级大于等于20或不符合黑白名单要求的粉丝勋章
     * @returns 数组,每个元素都是数组:[房间号,主播uid]
     */
    getRoomidUidList() {
      const biliStore = useBiliStore();
      if (biliStore.filteredFansMedals) {
        return biliStore.filteredFansMedals.filter(
          (medal) => medal.medal.level < 20 && (this.medalTasksConfig.isWhiteList ? this.medalTasksConfig.roomidList.includes(medal.room_info.room_id) : !this.medalTasksConfig.roomidList.includes(medal.room_info.room_id))
        ).map((medal) => [medal.room_info.room_id, medal.medal.target_id]).slice(0, 100);
      } else {
        return null;
      }
    }
    /**
     * 获取指定直播间的 area_id 和 parent_area_id
     *
     * @param roomid 房间号
     * @returns [area_id, parent_area_id]
     */
    async getAreaInfo(roomid) {
      try {
        const response = await BAPI.live.getInfoByRoom(roomid);
        this.logger.log(`BAPI.live.getInfoByRoom(${roomid}) response`, response);
        if (response.code === 0) {
          const room_info = response.data.room_info;
          return [room_info.area_id, room_info.parent_area_id];
        } else {
          return null;
        }
      } catch (error) {
        this.logger.error(
          `获取指定直播间的 area_id 和 parent_area_id(roomid = ${roomid}) 出错`,
          error
        );
        return null;
      }
    }
    async run() {
      this.logger.log("观看直播模块开始运行");
      if (this.config.enabled) {
        if (!isTimestampToday(this.config._lastCompleteTime)) {
          this.status = "running";
          if (!isTimestampToday(this.config._lastWatchTime, 0, 0)) {
            this.config._watchedSecondsToday = 0;
          } else {
            this.config._watchedSecondsToday -= this.config._watchedSecondsToday % 300;
          }
          this.config._lastWatchTime = tsm();
          const idList = this.getRoomidUidList();
          if (idList) {
            if (idList.length === 0) {
              this.status = "done";
              this.config._lastCompleteTime = tsm();
            } else {
              for (let i = 0; i < idList.length; i++) {
                const [roomid, uid] = idList[i];
                const areaInfo = await this.getAreaInfo(roomid);
                if (areaInfo && areaInfo.every((id) => id > 0)) {
                  new RoomHeart(
                    roomid,
                    areaInfo[0],
                    areaInfo[1],
                    uid,
                    this.config._watchedSecondsToday,
                    i === idList.length - 1 ? true : false
                  ).start();
                }
                await sleep(3e3);
              }
            }
          }
        } else {
          if (!isNowIn(0, 0, 0, 5)) {
            this.logger.log("今天已经完成过观看直播任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的观看直播任务已经完成过了,等到今天的00:05再执行");
          }
        }
      }
      const diff = delayToNextMoment();
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("距离观看直播模块下次运行时间:", diff.str);
    }
  }
  class DanmuTask extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "medalTasksConfig", this.moduleStore.moduleConfig.DailyTasks.LiveTasks.medalTasks);
      __publicField(this, "config", this.medalTasksConfig.danmu);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.LiveTasks.medalTasks.danmu = s;
    }
    /**
     * 获取粉丝勋章的房间号,过滤等级大于等于20或不符合黑白名单要求的粉丝勋章
     */
    getRoomidList() {
      const biliStore = useBiliStore();
      if (biliStore.filteredFansMedals) {
        return biliStore.filteredFansMedals.filter(
          (medal) => medal.medal.level < 20 && medal.room_info.room_id != 910884 && (this.medalTasksConfig.isWhiteList ? this.medalTasksConfig.roomidList.includes(medal.room_info.room_id) : !this.medalTasksConfig.roomidList.includes(medal.room_info.room_id))
        ).map((medal) => medal.room_info.room_id).slice(0, 100);
      } else {
        this.status = "error";
        return null;
      }
    }
    async sendDanmu(danmu, roomid) {
      try {
        const response = await BAPI.live.sendMsg(danmu, roomid);
        this.logger.log(`BAPI.live.sendMsg(${danmu}, ${roomid})`, response);
        if (response.code === 0) {
          this.logger.log(`在直播间 ${roomid} 发送弹幕 ${danmu} 成功`);
        } else {
          this.logger.error(`在直播间 ${roomid} 发送弹幕 ${danmu} 失败`, response.message);
        }
      } catch (error) {
        this.logger.error(`在直播间 ${roomid} 发送弹幕 ${danmu} 出错`, error);
      }
    }
    async run() {
      this.logger.log("发送弹幕模块开始运行");
      if (this.config.enabled) {
        if (!isTimestampToday(this.config._lastCompleteTime)) {
          this.status = "running";
          const roomIdList = this.getRoomidList();
          if (roomIdList) {
            const danmuList = this.config.list;
            for (let i = 0; i < roomIdList.length; i++) {
              const danmu = danmuList[i % danmuList.length];
              await this.sendDanmu(danmu, roomIdList[i]);
              await sleep(2e3);
            }
            this.config._lastCompleteTime = tsm();
            this.status = "done";
            this.logger.log("发送弹幕任务已完成");
          }
        } else {
          if (!isNowIn(0, 0, 0, 5)) {
            this.logger.log("今天已经完成过发送弹幕任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的发送弹幕任务已经完成过了,等到今天的00:05再执行");
          }
        }
      }
      this.moduleStore.emitter.emit("DailyTask_LiveTask_AppUserTask", {
        module: this.moduleName
      });
      const diff = delayToNextMoment();
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("距离发送弹幕模块下次运行时间:", diff.str);
    }
  }
  class GroupSignTask extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "config", this.moduleStore.moduleConfig.DailyTasks.OtherTasks.groupSign);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.OtherTasks.groupSign = s;
    }
    /**
     * 获取应援团 id 和拥有者 uid
     * @returns 数组,每个元素都是数组:[应援团 id,拥有者 uid]
     */
    async getGroupidOwneruidList() {
      try {
        const response = await BAPI.vc.myGroups();
        this.logger.log(`BAPI.vc.myGroups response`, response);
        if (response.code === 0) {
          return response.data.list.map((item) => [item.group_id, item.owner_uid]);
        } else {
          this.logger.error(`获取应援团信息失败`, response.message);
          this.status = "error";
        }
      } catch (error) {
        this.logger.error(`获取应援团信息出错`, error);
        this.status = "error";
      }
    }
    async sign(group_id, owner_uid) {
      try {
        const response = await BAPI.vc.signIn(group_id, owner_uid);
        this.logger.log(`BAPI.vc.signIn(${group_id}, ${owner_uid}) response`, response);
        if (response.code === 0) {
          this.logger.log(
            `应援团签到 应援团ID = ${group_id} 拥有者UID = ${owner_uid} 成功, 粉丝勋章亲密度+${response.data.add_num}`
          );
        } else {
          this.logger.error(
            `应援团签到 应援团ID = ${group_id} 拥有者UID = ${owner_uid} 失败`,
            response.message
          );
        }
      } catch (error) {
        this.logger.error(`应援团签到 应援团ID = ${group_id} 拥有者UID = ${owner_uid} 出错`, error);
      }
    }
    async run() {
      this.logger.log("应援团签到模块开始运行");
      if (this.config.enabled) {
        if (!isTimestampToday(this.config._lastCompleteTime, 8, 5)) {
          this.status = "running";
          const idList = await this.getGroupidOwneruidList();
          if (idList) {
            for (const [group_id, owner_uid] of idList) {
              await this.sign(group_id, owner_uid);
              await sleep(2e3);
            }
            this.config._lastCompleteTime = tsm();
            this.logger.log("应援团签到任务已完成");
            this.status = "done";
          }
        } else {
          if (!isNowIn(0, 0, 8, 5)) {
            this.logger.log("今天已经完成过应援团签到任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的应援团签到任务已经完成过了,等到今天早上八点零五分再次执行");
          }
        }
      }
      const diff = delayToNextMoment(8, 5);
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("距离应援团签到模块下次运行时间:", diff.str);
    }
  }
  class SilverToCoin extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "config", this.moduleStore.moduleConfig.DailyTasks.OtherTasks.silverToCoin);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.OtherTasks.silverToCoin = s;
    }
    async exchange() {
      try {
        const response = await BAPI.live.silver2coin();
        this.logger.log(`BAPI.live.silver2coin response`, response);
        if (response.code === 0) {
          this.logger.log(`银瓜子换硬币已完成,获得硬币:`, response.data.coin);
          this.config._lastCompleteTime = tsm();
          this.status = "done";
        } else if (response.code === 403) {
          this.logger.log("每天最多只能用银瓜子兑换1个硬币");
          this.config._lastCompleteTime = tsm();
          this.status = "done";
        } else {
          this.logger.error("银瓜子换硬币失败", response.message);
          this.status = "error";
        }
      } catch (err) {
        this.logger.error("银瓜子换硬币出错", err);
        this.status = "error";
      }
    }
    async run() {
      this.logger.log("银瓜子换硬币模块开始运行");
      if (this.config.enabled) {
        if (!isTimestampToday(this.config._lastCompleteTime)) {
          this.status = "running";
          await this.exchange();
        } else {
          if (!isNowIn(0, 0, 0, 5)) {
            this.logger.log("今天已经完成过银瓜子换硬币任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的银瓜子换硬币任务已经完成过了,等到今天的00:05再执行");
          }
        }
      }
      const diff = delayToNextMoment();
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("银瓜子换硬币模块下次运行时间:", diff.str);
    }
  }
  class CoinToSilver extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "config", this.moduleStore.moduleConfig.DailyTasks.OtherTasks.coinToSilver);
    }
    set status(s) {
      this.moduleStore.moduleStatus.DailyTasks.OtherTasks.coinToSilver = s;
    }
    async exchange() {
      try {
        const response = await BAPI.live.coin2silver(this.config.num);
        this.logger.log(`BAPI.live.coin2silver{${this.config.num}} response`, response);
        if (response.code === 0) {
          this.logger.log("硬币换银瓜子已完成,获得银瓜子:", response.data.silver);
          this.config._lastCompleteTime = tsm();
          this.status = "done";
        } else {
          this.logger.error("硬币换银瓜子失败", response.message);
          this.status = "error";
        }
      } catch (err) {
        this.logger.error("硬币换银瓜子出错", err);
        this.status = "error";
      }
    }
    async run() {
      this.logger.log("硬币换银瓜子模块开始运行");
      if (this.config.enabled) {
        if (!isTimestampToday(this.config._lastCompleteTime)) {
          this.status = "running";
          await this.exchange();
        } else {
          if (!isNowIn(0, 0, 0, 5)) {
            this.logger.log("今天已经完成过硬币换银瓜子任务了");
            this.status = "done";
          } else {
            this.logger.log("昨天的硬币换银瓜子任务已经完成过了,等到今天的00:05再执行");
          }
        }
      }
      const diff = delayToNextMoment();
      setTimeout(() => this.run(), diff.ms);
      this.logger.log("硬币换银瓜子模块下次运行时间:", diff.str);
    }
  }
  class SwitchLiveStreamQuality extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "config", this.moduleStore.moduleConfig.EnhanceExperience.switchLiveStreamQuality);
    }
    async waitForPlayer() {
      return new Promise((resolve, reject) => {
        const topWindow = _unsafeWindow.top ? _unsafeWindow.top : _unsafeWindow;
        const findPlayertimer = setInterval(() => {
          if (topWindow.livePlayer && _.has(topWindow.livePlayer, "getPlayerInfo") && _.has(topWindow.livePlayer, "switchQuality")) {
            clearInterval(findPlayertimer);
            clearTimeout(timeoutTimer);
            resolve(topWindow.livePlayer);
          }
        }, 200);
        const timeoutTimer = setTimeout(() => {
          clearInterval(findPlayertimer);
          clearTimeout(timeoutTimer);
          reject();
        }, 1e4);
      });
    }
    switchQuality(livePlayer) {
      const playerInfo = livePlayer.getPlayerInfo();
      if (playerInfo.liveStatus === 0) {
        this.logger.log("当前直播间未开播");
      } else if (playerInfo.qualityCandidates.length === 0) {
        this.logger.warn("当前直播间没有画质选项");
      } else {
        const targetQuality = playerInfo.qualityCandidates.find(
          ({ desc }) => desc === this.config.qualityDesc
        );
        if (targetQuality && playerInfo.quality !== targetQuality.qn) {
          livePlayer.switchQuality(targetQuality.qn);
          this.logger.log(`已将画质切换为${this.config.qualityDesc}`, targetQuality);
        }
      }
    }
    async run() {
      this.logger.log("自动切换画质模块开始运行");
      if (this.config.enabled) {
        try {
          const livePlayer = await this.waitForPlayer();
          await sleep(1e3);
          this.switchQuality(livePlayer);
        } catch (e) {
          this.logger.error("等待播放器超时");
        }
      }
    }
  }
  __publicField(SwitchLiveStreamQuality, "runMultiple", true);
  class BanP2P extends BaseModule {
    constructor() {
      super(...arguments);
      __publicField(this, "config", this.moduleStore.moduleConfig.EnhanceExperience.banp2p);
    }
    async banP2P() {
      var _a;
      const RTClist = [
        "RTCPeerConnection",
        "RTCDataChannel",
        "mozRTCPeerConnection",
        "webkitRTCPeerConnection",
        "DataChannel"
      ];
      for (const i of RTClist) {
        if (i in _unsafeWindow && _unsafeWindow.hasOwnProperty.call(_unsafeWindow, i) && ((_a = Object.getOwnPropertyDescriptor(_unsafeWindow, i)) == null ? void 0 : _a.configurable)) {
          delete _unsafeWindow[i];
        }
      }
    }
    async run() {
      this.logger.log("禁用P2P上传模块开始运行");
      if (this.config.enabled) {
        try {
          await this.banP2P();
        } catch (e) {
          this.logger.error("禁用P2P上传失败", e);
        }
      }
    }
  }
  __publicField(BanP2P, "runMultiple", true);
  const otherModules = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
    __proto__: null,
    DailyTask_LiveTask_AppUserTask: AppUserTask,
    DailyTask_LiveTask_DanmuTask: DanmuTask,
    DailyTask_LiveTask_LikeTask: LikeTask,
    DailyTask_LiveTask_SignTask: SignTask,
    DailyTask_LiveTask_WatchTask: WatchTask2,
    DailyTask_MainSiteTask_CoinTask: CoinTask,
    DailyTask_MainSiteTask_LoginTask: LoginTask,
    DailyTask_MainSiteTask_ShareTask: ShareTask,
    DailyTask_MainSiteTask_WatchTask: WatchTask$1,
    DailyTask_OtherTask_CoinToSilver: CoinToSilver,
    DailyTask_OtherTask_GroupSignTask: GroupSignTask,
    DailyTask_OtherTask_SilverToCoin: SilverToCoin,
    EnhanceExperience_BanP2P: BanP2P,
    EnhanceExperience_SwitchLiveStreamQuality: SwitchLiveStreamQuality
  }, Symbol.toStringTag, { value: "Module" }));
  function mitt(n) {
    return { all: n = n || /* @__PURE__ */ new Map(), on: function(t, e) {
      var i = n.get(t);
      i ? i.push(e) : n.set(t, [e]);
    }, off: function(t, e) {
      var i = n.get(t);
      i && (e ? i.splice(i.indexOf(e) >>> 0, 1) : n.set(t, []));
    }, emit: function(t, e) {
      var i = n.get(t);
      i && i.slice().map(function(n2) {
        n2(e);
      }), (i = n.get("*")) && i.slice().map(function(n2) {
        n2(t, e);
      });
    } };
  }
  const useCacheStore = pinia.defineStore("cache", () => {
    const cache = vue.reactive(Storage.getCache());
    const isMainBLTHRunning = vue.ref(false);
    function startAliveHeartBeat() {
      cache.lastAliveHeartBeatTime = Date.now();
      const timer = setInterval(() => cache.lastAliveHeartBeatTime = Date.now(), 5e3);
      window.onunload = () => {
        clearInterval(timer);
        cache.lastAliveHeartBeatTime = 0;
      };
    }
    function checkIfMainBLTHRunning() {
      if (cache.lastAliveHeartBeatTime !== 0 && Date.now() - cache.lastAliveHeartBeatTime < 8e3) {
        isMainBLTHRunning.value = true;
      } else {
        isMainBLTHRunning.value = false;
      }
    }
    vue.watch(cache, (newCache) => Storage.setCache(newCache));
    return {
      cache,
      isMainBLTHRunning,
      startAliveHeartBeat,
      checkIfMainBLTHRunning
    };
  });
  const defaultModuleStatus = {
    DailyTasks: {
      MainSiteTasks: {
        login: "",
        watch: "",
        coin: "",
        share: ""
      },
      LiveTasks: {
        sign: "",
        appUser: "",
        medalTasks: {
          danmu: "",
          like: "",
          watch: ""
        }
      },
      OtherTasks: {
        groupSign: "",
        silverToCoin: "",
        coinToSilver: ""
      }
    }
  };
  const useModuleStore = pinia.defineStore("module", () => {
    const moduleConfig = vue.reactive(Storage.getModuleConfig());
    const emitter = mitt();
    const moduleStatus = vue.reactive(defaultModuleStatus);
    async function loadModules() {
      const cacheStore = useCacheStore();
      for (const [name, Module] of Object.entries(defaultModules).sort(
        (a, b) => a[1].sequence - b[1].sequence
      )) {
        try {
          if (Module.runMultiple || !cacheStore.isMainBLTHRunning) {
            await new Module(name).run();
          }
        } catch (err) {
          new Logger("loadModules").error("加载默认模块时发生致命错误,挂机助手停止运行:", err);
          return;
        }
      }
      for (const [name, Module] of Object.entries(otherModules)) {
        if (Module.runMultiple || !cacheStore.isMainBLTHRunning) {
          new Module(name).run();
        }
      }
    }
    vue.watch(
      moduleConfig,
      _.debounce((newModuleConfig) => Storage.setModuleConfig(newModuleConfig), 250, {
        leading: true,
        trailing: true
      })
    );
    (function clearStatus() {
      setTimeout(() => {
        deepestIterate(moduleStatus, (_value, path) => {
          _.set(moduleStatus, path, "");
        });
        clearStatus();
      }, delayToNextMoment(0, 0).ms);
    })();
    return {
      moduleConfig,
      emitter,
      moduleStatus,
      loadModules
    };
  });
  const _hoisted_1$3 = { class: "title" };
  const _sfc_main$a = /* @__PURE__ */ vue.defineComponent({
    __name: "PanelHeader",
    setup(__props) {
      const uiStore = useUIStore();
      return (_ctx, _cache) => {
        const _component_el_icon = vue.resolveComponent("el-icon");
        const _component_el_text = vue.resolveComponent("el-text");
        return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
          vue.createElementVNode("div", {
            class: "collapse-btn",
            onClick: _cache[0] || (_cache[0] = ($event) => vue.unref(uiStore).changeCollapse())
          }, [
            vue.unref(uiStore).uiConfig.isCollapse ? (vue.openBlock(), vue.createBlock(_component_el_icon, { key: 0 }, {
              default: vue.withCtx(() => [
                vue.createVNode(vue.unref(ElementPlusIconsVue.Expand))
              ]),
              _: 1
            })) : (vue.openBlock(), vue.createBlock(_component_el_icon, { key: 1 }, {
              default: vue.withCtx(() => [
                vue.createVNode(vue.unref(ElementPlusIconsVue.Fold))
              ]),
              _: 1
            }))
          ]),
          vue.createElementVNode("div", _hoisted_1$3, [
            vue.createVNode(_component_el_text, {
              tag: "b",
              class: "header-big-text"
            }, {
              default: vue.withCtx(() => [
                vue.createTextVNode("控制面板")
              ]),
              _: 1
            }),
            vue.createVNode(_component_el_text, { class: "header-small-text" }, {
              default: vue.withCtx(() => [
                vue.createTextVNode(vue.toDisplayString(vue.unref(uiStore).activeMenuName), 1)
              ]),
              _: 1
            })
          ])
        ], 64);
      };
    }
  });
  const _export_sfc = (sfc, props) => {
    const target = sfc.__vccOpts || sfc;
    for (const [key, val] of props) {
      target[key] = val;
    }
    return target;
  };
  const PanelHeader = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-dda95e10"]]);
  const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
    __name: "PanelAside",
    setup(__props) {
      const uiStore = useUIStore();
      const items = [
        {
          icon: "Tasks",
          title: "每日任务",
          index: "DailyTasks",
          // 有子菜单,index 无所谓
          subs: [
            {
              title: "主站任务",
              index: "MainSiteTasks"
              // index 是组件名
            },
            {
              title: "直播任务",
              index: "LiveTasks"
            },
            {
              title: "其它任务",
              index: "OtherTasks"
            }
          ]
        },
        {
          icon: "Monitor",
          title: "体验优化",
          index: "EnhanceExperience"
        }
      ];
      return (_ctx, _cache) => {
        const _component_el_icon = vue.resolveComponent("el-icon");
        const _component_el_menu_item = vue.resolveComponent("el-menu-item");
        const _component_el_sub_menu = vue.resolveComponent("el-sub-menu");
        const _component_el_menu = vue.resolveComponent("el-menu");
        return vue.openBlock(), vue.createBlock(_component_el_menu, {
          "default-active": vue.unref(uiStore).uiConfig.activeMenuIndex,
          style: vue.normalizeStyle({ "min-height": vue.unref(uiStore).scrollBarHeight }),
          collapse: vue.unref(uiStore).uiConfig.isCollapse,
          "unique-opened": "",
          onSelect: vue.unref(uiStore).setActiveMenuIndex,
          id: "aside-el-menu"
        }, {
          default: vue.withCtx(() => [
            (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, vue.renderList(items, (item) => {
              return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
                item.subs ? (vue.openBlock(), vue.createBlock(_component_el_sub_menu, {
                  index: item.index,
                  key: item.index
                }, {
                  title: vue.withCtx(() => [
                    vue.createVNode(_component_el_icon, null, {
                      default: vue.withCtx(() => [
                        (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(item.icon)))
                      ]),
                      _: 2
                    }, 1024),
                    vue.createElementVNode("span", null, vue.toDisplayString(item.title), 1)
                  ]),
                  default: vue.withCtx(() => [
                    (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(item.subs, (subItem) => {
                      return vue.openBlock(), vue.createBlock(_component_el_menu_item, {
                        key: subItem.index,
                        index: subItem.index
                      }, {
                        default: vue.withCtx(() => [
                          vue.createTextVNode(vue.toDisplayString(subItem.title), 1)
                        ]),
                        _: 2
                      }, 1032, ["index"]);
                    }), 128))
                  ]),
                  _: 2
                }, 1032, ["index"])) : (vue.openBlock(), vue.createBlock(_component_el_menu_item, {
                  index: item.index,
                  key: item.index
                }, {
                  title: vue.withCtx(() => [
                    vue.createTextVNode(vue.toDisplayString(item.title), 1)
                  ]),
                  default: vue.withCtx(() => [
                    vue.createVNode(_component_el_icon, null, {
                      default: vue.withCtx(() => [
                        (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(item.icon)))
                      ]),
                      _: 2
                    }, 1024)
                  ]),
                  _: 2
                }, 1032, ["index"]))
              ], 64);
            }), 64))
          ]),
          _: 1
        }, 8, ["default-active", "style", "collapse", "onSelect"]);
      };
    }
  });
  const _sfc_main$8 = /* @__PURE__ */ vue.defineComponent({
    __name: "MainSiteTasks",
    setup(__props) {
      const moduleStore = useModuleStore();
      const config = moduleStore.moduleConfig.DailyTasks.MainSiteTasks;
      const status = moduleStore.moduleStatus.DailyTasks.MainSiteTasks;
      return (_ctx, _cache) => {
        const _component_el_switch = vue.resolveComponent("el-switch");
        const _component_Info = vue.resolveComponent("Info");
        const _component_TaskStatus = vue.resolveComponent("TaskStatus");
        const _component_el_space = vue.resolveComponent("el-space");
        const _component_el_row = vue.resolveComponent("el-row");
        const _component_el_option = vue.resolveComponent("el-option");
        const _component_el_select = vue.resolveComponent("el-select");
        const _component_el_text = vue.resolveComponent("el-text");
        const _component_el_divider = vue.resolveComponent("el-divider");
        const _component_el_link = vue.resolveComponent("el-link");
        return vue.openBlock(), vue.createElementBlock("div", null, [
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).login.enabled,
                    "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.unref(config).login.enabled = $event),
                    "active-text": "每日登录"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_Info, { id: "DailyTasks.MainSiteTasks.login" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).login
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).watch.enabled,
                    "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => vue.unref(config).watch.enabled = $event),
                    "active-text": "每日观看视频"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_Info, { id: "DailyTasks.MainSiteTasks.watch" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).watch
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).coin.enabled,
                    "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => vue.unref(config).coin.enabled = $event),
                    "active-text": "每日投币"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_el_select, {
                    modelValue: vue.unref(config).coin.num,
                    "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => vue.unref(config).coin.num = $event),
                    placeholder: "Select",
                    style: { "width": "64px" }
                  }, {
                    default: vue.withCtx(() => [
                      (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, vue.renderList(5, (i) => {
                        return vue.createVNode(_component_el_option, {
                          key: i,
                          label: i,
                          value: i
                        }, null, 8, ["label", "value"]);
                      }), 64))
                    ]),
                    _: 1
                  }, 8, ["modelValue"]),
                  vue.createVNode(_component_el_text, null, {
                    default: vue.withCtx(() => [
                      vue.createTextVNode("个")
                    ]),
                    _: 1
                  }),
                  vue.createVNode(_component_Info, { id: "DailyTasks.MainSiteTasks.coin" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).coin
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).share.enabled,
                    "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => vue.unref(config).share.enabled = $event),
                    "active-text": "每日分享视频"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_Info, { id: "DailyTasks.MainSiteTasks.share" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).share
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_divider),
          vue.createElementVNode("div", null, [
            vue.createVNode(_component_el_text, null, {
              default: vue.withCtx(() => [
                vue.createTextVNode("  主站每日任务的完成情况可在")
              ]),
              _: 1
            }),
            vue.createVNode(_component_el_link, {
              class: "el-link-va-baseline",
              rel: "noreferrer",
              type: "primary",
              href: "https://account.bilibili.com/account/home",
              target: "_blank"
            }, {
              default: vue.withCtx(() => [
                vue.createTextVNode("个人中心")
              ]),
              _: 1
            }),
            vue.createVNode(_component_el_text, null, {
              default: vue.withCtx(() => [
                vue.createTextVNode("查看。数据更新可能有一定的延时。")
              ]),
              _: 1
            })
          ])
        ]);
      };
    }
  });
  const _withScopeId$1 = (n) => (vue.pushScopeId("data-v-eac67691"), n = n(), vue.popScopeId(), n);
  const _hoisted_1$2 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("br", null, null, -1));
  const _hoisted_2$1 = { class: "avatar-wrap" };
  const _sfc_main$7 = /* @__PURE__ */ vue.defineComponent({
    __name: "LiveTasks",
    setup(__props) {
      const moduleStore = useModuleStore();
      const biliStore = useBiliStore();
      const config = moduleStore.moduleConfig.DailyTasks.LiveTasks;
      const status = moduleStore.moduleStatus.DailyTasks.LiveTasks;
      const medalDanmuPanelVisible = vue.ref(false);
      const danmuTableData = vue.computed(
        () => config.medalTasks.danmu.list.map((danmu) => {
          return { content: danmu };
        })
      );
      const handleEditDanmu = (index, row) => {
        ElementPlus.ElMessageBox.prompt("请输入新的弹幕内容", "修改弹幕", {
          confirmButtonText: "确认",
          cancelButtonText: "取消",
          inputPattern: /^.{1,30}$/,
          inputErrorMessage: "弹幕内容不得为空且长度不能超过30",
          inputValue: row.content,
          lockScroll: false
        }).then(({ value }) => {
          config.medalTasks.danmu.list[index] = value;
        }).catch(() => {
        });
      };
      const handleDeleteDanmu = (index) => {
        if (config.medalTasks.danmu.list.length === 1) {
          ElementPlus.ElMessage.warning({
            message: "至少要有一条弹幕",
            appendTo: ".el-dialog"
          });
          return;
        }
        config.medalTasks.danmu.list.splice(index, 1);
      };
      const handleAddDanmu = () => {
        ElementPlus.ElMessageBox.prompt("请输入新增的弹幕内容", "新增弹幕", {
          confirmButtonText: "确认",
          cancelButtonText: "取消",
          inputPattern: /^.{1,30}$/,
          inputErrorMessage: "弹幕内容不得为空且长度不能超过30",
          lockScroll: false
        }).then(({ value }) => {
          config.medalTasks.danmu.list.push(value);
        }).catch(() => {
        });
      };
      const medalInfoPanelVisible = vue.ref(false);
      const medalInfoTableData = vue.computed(
        () => {
          var _a;
          return (_a = biliStore.filteredFansMedals) == null ? void 0 : _a.map((medal) => ({
            avatar: medal.anchor_info.avatar,
            nick_name: medal.anchor_info.nick_name,
            medal_name: medal.medal.medal_name,
            medal_level: medal.medal.level,
            roomid: medal.room_info.room_id
          }));
        }
      );
      const medalInfoLoading = vue.ref(false);
      let firstClickEditList = true;
      const handleEditList = () => {
        medalInfoPanelVisible.value = !medalInfoPanelVisible.value;
        if (firstClickEditList) {
          if (!biliStore.fansMedals) {
            medalInfoLoading.value = true;
            const unwatch = vue.watch(medalInfoTableData, (newData) => {
              if (newData) {
                unwatch();
                firstClickEditList = false;
                initSelection(medalInfoTableData.value);
                medalInfoLoading.value = false;
              }
            });
            moduleStore.emitter.emit("BiliInfo", {
              target: "getFansMetals"
            });
          } else {
            initSelection(medalInfoTableData.value);
          }
        }
      };
      const medalInfoTableRef = vue.ref();
      let lockConfig = false;
      const initSelection = (rows) => {
        lockConfig = true;
        if (rows) {
          const unwatch = vue.watch(
            () => medalInfoTableRef.value,
            (newValue) => {
              setTimeout(() => unwatch(), 0);
              if (newValue) {
                config.medalTasks.roomidList.forEach(
                  (roomid) => newValue.toggleRowSelection(
                    rows.find((row) => row.roomid === roomid),
                    true
                  )
                );
              }
            },
            { immediate: true }
          );
        }
        lockConfig = false;
      };
      function handleSelectionChange(selectedRows) {
        if (!lockConfig) {
          config.medalTasks.roomidList = selectedRows.map((row) => row.roomid);
        }
      }
      return (_ctx, _cache) => {
        const _component_el_switch = vue.resolveComponent("el-switch");
        const _component_Info = vue.resolveComponent("Info");
        const _component_TaskStatus = vue.resolveComponent("TaskStatus");
        const _component_el_space = vue.resolveComponent("el-space");
        const _component_el_row = vue.resolveComponent("el-row");
        const _component_el_divider = vue.resolveComponent("el-divider");
        const _component_el_button = vue.resolveComponent("el-button");
        const _component_el_option = vue.resolveComponent("el-option");
        const _component_el_select = vue.resolveComponent("el-select");
        const _component_el_text = vue.resolveComponent("el-text");
        const _component_el_link = vue.resolveComponent("el-link");
        const _component_el_table_column = vue.resolveComponent("el-table-column");
        const _component_el_dialog = vue.resolveComponent("el-dialog");
        const _component_el_image = vue.resolveComponent("el-image");
        const _directive_loading = vue.resolveDirective("loading");
        return vue.openBlock(), vue.createElementBlock("div", null, [
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).sign.enabled,
                    "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.unref(config).sign.enabled = $event),
                    "active-text": "直播签到"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_Info, { id: "DailyTasks.LiveTasks.sign" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).sign
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).appUser.enabled,
                    "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => vue.unref(config).appUser.enabled = $event),
                    disabled: "",
                    "active-text": "APP用户任务"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_Info, { id: "DailyTasks.LiveTasks.appUser" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).appUser
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_divider),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).medalTasks.like.enabled,
                    "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => vue.unref(config).medalTasks.like.enabled = $event),
                    "active-text": "给主播点赞"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_Info, { id: "DailyTasks.LiveTasks.medalTasks.like" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).medalTasks.like
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).medalTasks.danmu.enabled,
                    "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => vue.unref(config).medalTasks.danmu.enabled = $event),
                    "active-text": "发送弹幕"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_el_button, {
                    type: "primary",
                    size: "small",
                    icon: vue.unref(ElementPlusIconsVue.Edit),
                    onClick: _cache[4] || (_cache[4] = ($event) => medalDanmuPanelVisible.value = !medalDanmuPanelVisible.value)
                  }, {
                    default: vue.withCtx(() => [
                      vue.createTextVNode("编辑弹幕")
                    ]),
                    _: 1
                  }, 8, ["icon"]),
                  vue.createVNode(_component_Info, { id: "DailyTasks.LiveTasks.medalTasks.danmu" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).medalTasks.danmu
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).medalTasks.watch.enabled,
                    "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => vue.unref(config).medalTasks.watch.enabled = $event),
                    "active-text": "观看直播"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_el_select, {
                    modelValue: vue.unref(config).medalTasks.watch.time,
                    "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => vue.unref(config).medalTasks.watch.time = $event),
                    placeholder: "Select",
                    style: { "width": "64px" }
                  }, {
                    default: vue.withCtx(() => [
                      (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, vue.renderList(24, (i) => {
                        return vue.createVNode(_component_el_option, {
                          key: i,
                          label: i * 5,
                          value: i * 5
                        }, null, 8, ["label", "value"]);
                      }), 64))
                    ]),
                    _: 1
                  }, 8, ["modelValue"]),
                  vue.createVNode(_component_el_text, null, {
                    default: vue.withCtx(() => [
                      vue.createTextVNode("分钟")
                    ]),
                    _: 1
                  }),
                  vue.createVNode(_component_Info, { id: "DailyTasks.LiveTasks.medalTasks.watch" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).medalTasks.watch
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).medalTasks.isWhiteList,
                    "onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => vue.unref(config).medalTasks.isWhiteList = $event),
                    "active-text": "白名单",
                    "inactive-text": "黑名单"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_el_button, {
                    type: "primary",
                    size: "small",
                    icon: vue.unref(ElementPlusIconsVue.Edit),
                    onClick: handleEditList
                  }, {
                    default: vue.withCtx(() => [
                      vue.createTextVNode("编辑名单")
                    ]),
                    _: 1
                  }, 8, ["icon"]),
                  vue.createVNode(_component_Info, { id: "DailyTasks.LiveTasks.medalTasks.list" })
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_divider),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_text, null, {
                default: vue.withCtx(() => [
                  vue.createTextVNode("直播任务相关信息可在")
                ]),
                _: 1
              }),
              vue.createVNode(_component_el_link, {
                class: "el-link-va-baseline",
                rel: "noreferrer",
                type: "primary",
                href: "https://link.bilibili.com/p/help/index#/audience-fans-medal",
                target: "_blank"
              }, {
                default: vue.withCtx(() => [
                  vue.createTextVNode("帮助中心")
                ]),
                _: 1
              }),
              vue.createVNode(_component_el_text, null, {
                default: vue.withCtx(() => [
                  vue.createTextVNode("查看。")
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          _hoisted_1$2,
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_text, { tag: "b" }, {
                default: vue.withCtx(() => [
                  vue.createTextVNode("注意:")
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_text, null, {
                default: vue.withCtx(() => [
                  vue.createTextVNode("  由于每天能通过完成任务获得亲密度的粉丝勋章数量有限,目前脚本仅为最多100个等级小于20的粉丝勋章完成给主播点赞,发送弹幕,观看直播任务。")
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_dialog, {
            modelValue: medalDanmuPanelVisible.value,
            "onUpdate:modelValue": _cache[8] || (_cache[8] = ($event) => medalDanmuPanelVisible.value = $event),
            title: "编辑弹幕内容",
            "lock-scroll": false,
            width: "40%"
          }, {
            footer: vue.withCtx(() => [
              vue.createVNode(_component_el_button, {
                type: "primary",
                onClick: handleAddDanmu
              }, {
                default: vue.withCtx(() => [
                  vue.createTextVNode("新增弹幕")
                ]),
                _: 1
              })
            ]),
            default: vue.withCtx(() => [
              vue.createVNode(vue.unref(ElementPlus.ElTable), {
                data: danmuTableData.value,
                "max-height": "500"
              }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_table_column, {
                    type: "index",
                    width: "50"
                  }),
                  vue.createVNode(_component_el_table_column, {
                    prop: "content",
                    label: "弹幕内容"
                  }),
                  vue.createVNode(_component_el_table_column, {
                    label: "操作",
                    width: "220",
                    align: "center"
                  }, {
                    default: vue.withCtx((scope) => [
                      vue.createVNode(_component_el_button, {
                        text: "",
                        icon: vue.unref(ElementPlusIconsVue.Edit),
                        onClick: ($event) => handleEditDanmu(scope.$index, scope.row)
                      }, {
                        default: vue.withCtx(() => [
                          vue.createTextVNode(" 修改 ")
                        ]),
                        _: 2
                      }, 1032, ["icon", "onClick"]),
                      vue.createVNode(_component_el_button, {
                        text: "",
                        icon: vue.unref(ElementPlusIconsVue.Delete),
                        type: "danger",
                        onClick: ($event) => handleDeleteDanmu(scope.$index)
                      }, {
                        default: vue.withCtx(() => [
                          vue.createTextVNode(" 删除 ")
                        ]),
                        _: 2
                      }, 1032, ["icon", "onClick"])
                    ]),
                    _: 1
                  })
                ]),
                _: 1
              }, 8, ["data"])
            ]),
            _: 1
          }, 8, ["modelValue"]),
          vue.createVNode(_component_el_dialog, {
            modelValue: medalInfoPanelVisible.value,
            "onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => medalInfoPanelVisible.value = $event),
            title: "编辑粉丝勋章名单",
            "lock-scroll": false,
            width: "40%"
          }, {
            default: vue.withCtx(() => [
              vue.withDirectives((vue.openBlock(), vue.createBlock(vue.unref(ElementPlus.ElTable), {
                ref_key: "medalInfoTableRef",
                ref: medalInfoTableRef,
                data: medalInfoTableData.value,
                "max-height": "500",
                "empty-text": "没有粉丝勋章",
                onSelectionChange: handleSelectionChange
              }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_table_column, {
                    type: "selection",
                    align: "center",
                    width: "55"
                  }),
                  vue.createVNode(_component_el_table_column, {
                    prop: "avatar",
                    label: "头像"
                  }, {
                    default: vue.withCtx((scope) => [
                      vue.createElementVNode("div", _hoisted_2$1, [
                        vue.createVNode(_component_el_image, {
                          src: scope.row.avatar,
                          loading: "lazy",
                          referrerpolicy: "origin",
                          class: "avatar"
                        }, {
                          error: vue.withCtx(() => [
                            vue.createVNode(_component_el_image, {
                              src: "//i0.hdslb.com/bfs/face/member/noface.jpg",
                              referrerpolicy: "origin",
                              class: "avatar"
                            })
                          ]),
                          _: 2
                        }, 1032, ["src"])
                      ])
                    ]),
                    _: 1
                  }),
                  vue.createVNode(_component_el_table_column, {
                    prop: "nick_name",
                    label: "昵称"
                  }),
                  vue.createVNode(_component_el_table_column, {
                    prop: "medal_name",
                    label: "粉丝勋章"
                  }),
                  vue.createVNode(_component_el_table_column, {
                    prop: "medal_level",
                    label: "等级",
                    sortable: ""
                  }),
                  vue.createVNode(_component_el_table_column, {
                    prop: "roomid",
                    label: "房间号"
                  }, {
                    default: vue.withCtx((scope) => [
                      vue.createVNode(_component_el_link, {
                        href: "https://live.bilibili.com/" + scope.row.roomid + "?visit_id=",
                        rel: "noreferrer",
                        type: "primary",
                        target: "_blank"
                      }, {
                        default: vue.withCtx(() => [
                          vue.createTextVNode(vue.toDisplayString(scope.row.roomid), 1)
                        ]),
                        _: 2
                      }, 1032, ["href"])
                    ]),
                    _: 1
                  })
                ]),
                _: 1
              }, 8, ["data"])), [
                [_directive_loading, medalInfoLoading.value]
              ])
            ]),
            _: 1
          }, 8, ["modelValue"])
        ]);
      };
    }
  });
  const LiveTasks = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-eac67691"]]);
  const _sfc_main$6 = /* @__PURE__ */ vue.defineComponent({
    __name: "OtherTasks",
    setup(__props) {
      const moduleStore = useModuleStore();
      const config = moduleStore.moduleConfig.DailyTasks.OtherTasks;
      const status = moduleStore.moduleStatus.DailyTasks.OtherTasks;
      return (_ctx, _cache) => {
        const _component_el_switch = vue.resolveComponent("el-switch");
        const _component_Info = vue.resolveComponent("Info");
        const _component_TaskStatus = vue.resolveComponent("TaskStatus");
        const _component_el_space = vue.resolveComponent("el-space");
        const _component_el_row = vue.resolveComponent("el-row");
        const _component_el_text = vue.resolveComponent("el-text");
        const _component_el_option = vue.resolveComponent("el-option");
        const _component_el_select = vue.resolveComponent("el-select");
        const _component_el_divider = vue.resolveComponent("el-divider");
        return vue.openBlock(), vue.createElementBlock("div", null, [
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).groupSign.enabled,
                    "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.unref(config).groupSign.enabled = $event),
                    "active-text": "应援团签到"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_Info, { id: "DailyTasks.OtherTasks.groupSign" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).groupSign
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).silverToCoin.enabled,
                    "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => vue.unref(config).silverToCoin.enabled = $event),
                    "active-text": "银瓜子换硬币"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_Info, { id: "DailyTasks.OtherTasks.silverToCoin" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).silverToCoin
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).coinToSilver.enabled,
                    "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => vue.unref(config).coinToSilver.enabled = $event),
                    "active-text": "硬币换银瓜子"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_el_text, null, {
                    default: vue.withCtx(() => [
                      vue.createTextVNode("花费硬币")
                    ]),
                    _: 1
                  }),
                  vue.createVNode(_component_el_select, {
                    modelValue: vue.unref(config).coinToSilver.num,
                    "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => vue.unref(config).coinToSilver.num = $event),
                    placeholder: "Select",
                    style: { "width": "64px" }
                  }, {
                    default: vue.withCtx(() => [
                      (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, vue.renderList(50, (i) => {
                        return vue.createVNode(_component_el_option, {
                          key: i,
                          label: i,
                          value: i
                        }, null, 8, ["label", "value"]);
                      }), 64))
                    ]),
                    _: 1
                  }, 8, ["modelValue"]),
                  vue.createVNode(_component_el_text, null, {
                    default: vue.withCtx(() => [
                      vue.createTextVNode("个")
                    ]),
                    _: 1
                  }),
                  vue.createVNode(_component_Info, { id: "DailyTasks.OtherTasks.coinToSilver" }),
                  vue.createVNode(_component_TaskStatus, {
                    status: vue.unref(status).coinToSilver
                  }, null, 8, ["status"])
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_divider)
        ]);
      };
    }
  });
  const _sfc_main$5 = /* @__PURE__ */ vue.defineComponent({
    __name: "EnhanceExperience",
    setup(__props) {
      const moduleStore = useModuleStore();
      const config = moduleStore.moduleConfig.EnhanceExperience;
      const qualityDescList = ["原画", "蓝光PRO", "蓝光", "超清PRO", "超清", "高清"];
      return (_ctx, _cache) => {
        const _component_el_switch = vue.resolveComponent("el-switch");
        const _component_el_option = vue.resolveComponent("el-option");
        const _component_el_select = vue.resolveComponent("el-select");
        const _component_Info = vue.resolveComponent("Info");
        const _component_el_space = vue.resolveComponent("el-space");
        const _component_el_row = vue.resolveComponent("el-row");
        const _component_el_divider = vue.resolveComponent("el-divider");
        return vue.openBlock(), vue.createElementBlock("div", null, [
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).switchLiveStreamQuality.enabled,
                    "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.unref(config).switchLiveStreamQuality.enabled = $event),
                    "active-text": "自动切换画质"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_el_select, {
                    modelValue: vue.unref(config).switchLiveStreamQuality.qualityDesc,
                    "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => vue.unref(config).switchLiveStreamQuality.qualityDesc = $event),
                    placeholder: "Select",
                    style: { "width": "110px" }
                  }, {
                    default: vue.withCtx(() => [
                      (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, vue.renderList(qualityDescList, (i) => {
                        return vue.createVNode(_component_el_option, {
                          key: i,
                          label: i,
                          value: i
                        }, null, 8, ["label", "value"]);
                      }), 64))
                    ]),
                    _: 1
                  }, 8, ["modelValue"]),
                  vue.createVNode(_component_Info, { id: "EnhanceExperience.switchLiveStreamQuality" })
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_row, null, {
            default: vue.withCtx(() => [
              vue.createVNode(_component_el_space, { wrap: "" }, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_switch, {
                    modelValue: vue.unref(config).banp2p.enabled,
                    "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => vue.unref(config).banp2p.enabled = $event),
                    "active-text": "禁用P2P上传"
                  }, null, 8, ["modelValue"]),
                  vue.createVNode(_component_Info, { id: "EnhanceExperience.banp2p" })
                ]),
                _: 1
              })
            ]),
            _: 1
          }),
          vue.createVNode(_component_el_divider)
        ]);
      };
    }
  });
  const __default__ = {
    components: {
      MainSiteTasks: _sfc_main$8,
      LiveTasks,
      OtherTasks: _sfc_main$6,
      EnhanceExperience: _sfc_main$5
    }
  };
  const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
    ...__default__,
    __name: "PanelMain",
    setup(__props) {
      const uiStore = useUIStore();
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(vue.unref(uiStore).uiConfig.activeMenuIndex));
      };
    }
  });
  const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
    __name: "App",
    setup(__props) {
      const uiStore = useUIStore();
      const moduleStore = useModuleStore();
      const logger = new Logger("App.vue");
      let isShowPanel = uiStore.uiConfig.isShowPanel;
      uiStore.uiConfig.isShowPanel = false;
      let livePlayer;
      let button;
      function setPanelSize() {
        const rect = livePlayer.getBoundingClientRect();
        uiStore.baseStyleValue.top = rect.top + window.scrollY;
        uiStore.baseStyleValue.left = rect.left + window.scrollX;
        uiStore.baseStyleValue.height = rect.height;
        uiStore.baseStyleValue.width = rect.width * 0.4;
      }
      function buttonOnClick() {
        uiStore.changeShowPanel();
        button.innerText = uiStore.isShowPanelButtonText;
      }
      const throttleButtoOnClick = _.throttle(buttonOnClick, 300);
      moduleStore.loadModules();
      window.onload = () => {
        livePlayer = dq("#live-player-ctnr");
        if (livePlayer) {
          setPanelSize();
          pollingQuery(document, ".left-ctnr.left-header-area", 300, 3e3).then((playerHeaderLeft) => {
            button = dce("button");
            button.setAttribute("class", "blth_btn");
            button.onclick = throttleButtoOnClick;
            button.innerText = uiStore.isShowPanelButtonText;
            playerHeaderLeft.append(button);
            if (!isSelfTopFrame()) {
              hotkeys(
                "alt+b",
                {
                  element: topFrameDocuemnt()
                },
                throttleButtoOnClick
              );
            }
            hotkeys("alt+b", throttleButtoOnClick);
          }).catch(() => logger.error("Can't find playerHeaderLeft in time"));
          window.onresize = setPanelSize;
          const observer = new MutationObserver(() => setPanelSize());
          observer.observe(document.documentElement, { attributes: true });
          observer.observe(document.body, { attributes: true });
          if (isShowPanel) {
            uiStore.uiConfig.isShowPanel = true;
          }
        } else {
          logger.error("livePlayer not found");
        }
      };
      return (_ctx, _cache) => {
        const _component_el_header = vue.resolveComponent("el-header");
        const _component_el_aside = vue.resolveComponent("el-aside");
        const _component_el_main = vue.resolveComponent("el-main");
        const _component_el_container = vue.resolveComponent("el-container");
        const _component_el_scrollbar = vue.resolveComponent("el-scrollbar");
        const _component_el_collapse_transition = vue.resolveComponent("el-collapse-transition");
        return vue.openBlock(), vue.createBlock(_component_el_collapse_transition, null, {
          default: vue.withCtx(() => [
            vue.withDirectives(vue.createElementVNode("div", {
              style: vue.normalizeStyle(vue.unref(uiStore).baseStyle),
              class: "base"
            }, [
              vue.createVNode(_component_el_container, null, {
                default: vue.withCtx(() => [
                  vue.createVNode(_component_el_header, { class: "header" }, {
                    default: vue.withCtx(() => [
                      vue.createVNode(PanelHeader)
                    ]),
                    _: 1
                  }),
                  vue.createVNode(_component_el_scrollbar, {
                    height: vue.unref(uiStore).scrollBarHeight
                  }, {
                    default: vue.withCtx(() => [
                      vue.createVNode(_component_el_container, null, {
                        default: vue.withCtx(() => [
                          vue.createVNode(_component_el_aside, { class: "aside" }, {
                            default: vue.withCtx(() => [
                              vue.createVNode(_sfc_main$9)
                            ]),
                            _: 1
                          }),
                          vue.createVNode(_component_el_main, { class: "main" }, {
                            default: vue.withCtx(() => [
                              (vue.openBlock(), vue.createBlock(vue.KeepAlive, null, [
                                vue.createVNode(vue.Transition, {
                                  name: "fade",
                                  mode: "out-in"
                                }, {
                                  default: vue.withCtx(() => [
                                    vue.createVNode(_sfc_main$4)
                                  ]),
                                  _: 1
                                })
                              ], 1024))
                            ]),
                            _: 1
                          })
                        ]),
                        _: 1
                      })
                    ]),
                    _: 1
                  }, 8, ["height"])
                ]),
                _: 1
              })
            ], 4), [
              [vue.vShow, vue.unref(uiStore).uiConfig.isShowPanel]
            ])
          ]),
          _: 1
        });
      };
    }
  });
  const App = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-4aed17ff"]]);
  const cssLoader = (e) => {
    const t = GM_getResourceText(e), o = document.createElement("style");
    return o.innerText = t, document.head.append(o), t;
  };
  cssLoader("element-plus/dist/index.css");
  const _sfc_main$2 = {};
  const _hoisted_1$1 = {
    xmlns: "http://www.w3.org/2000/svg",
    width: "128",
    height: "128",
    class: "icon",
    viewBox: "0 0 1024 1024"
  };
  const _hoisted_2 = /* @__PURE__ */ vue.createElementVNode("path", { d: "M831.825 63.94H191.94c-70.692 0-128 57.308-128 128v639.885c0 70.692 57.308 128 128 128h639.885c70.692 0 128-57.308 128-128V191.94c0-70.692-57.308-128-128-128zM895.885 832a63.835 63.835 0 0 1-63.973 63.886H192.088c-17.112 0-33.27-6.575-45.372-18.676S127.88 849.112 127.88 832V192a64.236 64.236 0 0 1 64.208-64.12h639.824A64.038 64.038 0 0 1 895.885 192v640z" }, null, -1);
  const _hoisted_3 = /* @__PURE__ */ vue.createElementVNode("path", { d: "M791.998 351.852H536a31.97 31.97 0 0 0 0 63.94h256a31.97 31.97 0 0 0 0-63.94zm0 256.121H536a31.97 31.97 0 0 0 0 63.94h256a31.97 31.97 0 0 0 0-63.94zm-447.996-79.975c-61.856 0-111.986 50.144-111.986 111.985S282.16 751.97 344.002 751.97s111.985-50.144 111.985-111.986-50.13-111.985-111.985-111.985zm33.982 145.982a48.045 48.045 0 1 1 14.088-33.982 47.746 47.746 0 0 1-14.088 33.986zm39.412-376.586L311.999 402.787l-41.391-41.395a31.97 31.97 0 1 0-45.213 45.213l63.997 64.002a31.97 31.97 0 0 0 45.214 0l128-128a31.97 31.97 0 0 0-45.21-45.213z" }, null, -1);
  const _hoisted_4 = [
    _hoisted_2,
    _hoisted_3
  ];
  function _sfc_render(_ctx, _cache) {
    return vue.openBlock(), vue.createElementBlock("svg", _hoisted_1$1, _hoisted_4);
  }
  const TasksIcon = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render]]);
  const help_info = {
    DailyTasks: {
      MainSiteTasks: {
        login: {
          title: "每日登录",
          message: "完成主站的每日登录任务。"
        },
        watch: {
          title: "每日观看视频",
          message: vue.h("p", [
            vue.h("div", "完成主站的每日观看视频任务。"),
            vue.h("div", "从动态中选取视频观看,会产生观看历史记录。")
          ])
        },
        coin: {
          title: "每日投币",
          message: vue.h("p", [
            vue.h("div", "完成主站的每日投币任务。"),
            vue.h("div", "从动态中选取视频投币,会根据你今天已经投过的币的数量计算还要投几个币。")
          ])
        },
        share: {
          title: "每日分享视频",
          message: vue.h("p", [
            vue.h("div", "完成主站的每日分享视频任务。"),
            vue.h("div", "不会真的分享到某处。")
          ])
        }
      },
      LiveTasks: {
        sign: {
          title: "直播签到",
          message: vue.h("p", [
            vue.h("div", "完成直播签到任务。"),
            vue.h("div", "完成后会移除当前直播间右上角签到窗口中的签到按钮。")
          ])
        },
        appUser: {
          title: "APP用户任务",
          message: vue.h("p", [
            vue.h("div", "完成APP用户任务并领取奖励。"),
            vue.h("div", [
              vue.h(
                "strong",
                "由于曾经的APP用户任务下架已久,目前的新任务(观看新主播直播并发弹幕)又没有对全部用户开放,故改功能暂时被禁用。"
              ),
              vue.h("div", [
                vue.h(
                  "span",
                  "在APP中观看直播时右下角可能会有个电池图标,点击即可查看APP用户任务内容。并非所有账号都可以参加该任务。  如果开启了发送弹幕功能,该功能会在发送弹幕功能运行完毕后再运行。如果之前发送的弹幕数量不够,会先在直播间"
                ),
                vue.h(
                  "a",
                  {
                    class: "el-link el-link--primary is-underline el-link-va-baseline",
                    href: "https://live.bilibili.com/22474988",
                    rel: "noreferrer",
                    target: "_blank"
                  },
                  "22474988"
                ),
                vue.h("span", "发送弹幕再领取奖励。")
              ])
            ])
          ])
        },
        medalTasks: {
          list: {
            title: "黑白名单",
            message: vue.h("p", [
              vue.h("div", "为更精细地控制为哪些粉丝勋章执行任务,你可以使用黑名单或白名单模式。"),
              vue.h("div", [
                vue.h("li", [
                  vue.h("span", "黑名单:仅为"),
                  vue.h("strong", "不在"),
                  vue.h("span", "名单中的粉丝勋章执行任务。")
                ]),
                vue.h("li", [
                  vue.h("span", "白名单:仅为"),
                  vue.h("strong", "在"),
                  vue.h("span", "名单中的粉丝勋章执行任务。")
                ])
              ]),
              vue.h("div", "点击编辑名单按钮,然后使用第一列的多选框即可编辑名单中的粉丝勋章。")
            ])
          },
          like: {
            title: "给主播点赞",
            message: vue.h("p", [
              vue.h("div", "在你的每个粉丝勋章对应的直播间给主播点赞。"),
              vue.h("div", "部分直播间无法完成该任务,原因未知。")
            ])
          },
          danmu: {
            title: "发送弹幕",
            message: vue.h("p", [
              vue.h("div", "在你的每个粉丝勋章对应的直播间发送一条弹幕。"),
              vue.h("div", [
                vue.h("span", "点击编辑弹幕按钮编辑发送的弹幕,脚本会从中按顺序循环抽取弹幕发送。"),
                vue.h("span", "部分直播间无法完成该任务,可能的原因有:,"),
                vue.h("li", "你被禁言了"),
                vue.h("li", "发言有粉丝勋章等级要求"),
                vue.h("li", [
                  vue.h("span", "特殊直播间(比如"),
                  vue.h(
                    "a",
                    { href: "https://live.bilibili.com/54", rel: "noreferrer", target: "_blank" },
                    "54"
                  ),
                  vue.h("span", ")")
                ])
              ])
            ])
          },
          watch: {
            title: "观看直播",
            message: vue.h("p", [
              vue.h("div", "完成观看持有粉丝勋章对应主播直播的任务。"),
              vue.h(
                "div",
                "部分直播间因为没有设置直播分区导致任务无法完成。主播当前是否开播不会影响该任务的完成。"
              )
            ])
          }
        }
      },
      OtherTasks: {
        groupSign: {
          title: "应援团签到",
          message: "完成应援团签到任务。"
        },
        silverToCoin: {
          title: "银瓜子换硬币",
          message: vue.h("p", [
            vue.h("div", "把银瓜子兑换为硬币。"),
            vue.h("div", "具体兑换规则请点击直播间页面的“立即充值→银瓜子商店”查看。")
          ])
        },
        coinToSilver: {
          title: "硬币换银瓜子",
          message: vue.h("p", [
            vue.h("div", "把硬币兑换为银瓜子。"),
            vue.h("div", "具体兑换规则请点击直播间页面的“立即充值→银瓜子商店”查看。")
          ])
        }
      }
    },
    EnhanceExperience: {
      switchLiveStreamQuality: {
        title: "自动切换画质",
        message: "打开直播间后自动把播放器切换到指定画质。"
      },
      banp2p: {
        title: "禁用P2P上传",
        message: "禁用直播间的P2P上传,防止B站白嫖宽带。"
      }
    }
  };
  const _withScopeId = (n) => (vue.pushScopeId("data-v-c1d8df5e"), n = n(), vue.popScopeId(), n);
  const _hoisted_1 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("svg", {
    xmlns: "http://www.w3.org/2000/svg",
    width: "128",
    height: "128",
    class: "icon",
    viewBox: "0 0 1024 1024"
  }, [
    /* @__PURE__ */ vue.createElementVNode("path", {
      fill: "#276BC0",
      d: "M512.67 959.47c-246.343 0-446.76-200.632-446.76-447.24S266.326 64.98 512.67 64.98s446.76 200.642 446.76 447.25-200.416 447.24-446.76 447.24zm0-829.04c-210.291 0-381.38 171.283-381.38 381.8s171.089 381.79 381.38 381.79 381.381-171.273 381.381-381.79-171.09-381.8-381.38-381.8z"
    }),
    /* @__PURE__ */ vue.createElementVNode("path", {
      fill: "#276BC0",
      d: "M447.29 317.172a63.891 63.959 0 1 0 130.76 0 63.891 63.959 0 1 0-130.76 0Zm64.907 503.047c-30.093 0-54.235-24.416-54.235-54.541V482.062c0-30.126 24.142-54.541 54.235-54.541 30.094 0 54.236 24.416 54.236 54.541v283.616c0 30.125-24.142 54.54-54.236 54.54z"
    })
  ], -1));
  const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
    __name: "InfoIcon",
    props: {
      id: {}
    },
    setup(__props) {
      const props = __props;
      const open = () => {
        const { title, message } = _.get(help_info, props.id, {
          title: "无",
          message: "无"
        });
        ElementPlus.ElMessageBox({
          title,
          message,
          lockScroll: false,
          autofocus: true,
          confirmButtonText: "OK"
        });
      };
      return (_ctx, _cache) => {
        const _component_el_icon = vue.resolveComponent("el-icon");
        return vue.openBlock(), vue.createBlock(_component_el_icon, {
          class: "info-icon",
          onClick: open
        }, {
          default: vue.withCtx(() => [
            _hoisted_1
          ]),
          _: 1
        });
      };
    }
  });
  const InfoIcon = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-c1d8df5e"]]);
  const _sfc_main = /* @__PURE__ */ vue.defineComponent({
    __name: "TaskStatusIcon",
    props: {
      status: {}
    },
    setup(__props) {
      return (_ctx, _cache) => {
        const _component_Loading = vue.resolveComponent("Loading");
        const _component_el_icon = vue.resolveComponent("el-icon");
        const _component_Select = vue.resolveComponent("Select");
        const _component_CloseBold = vue.resolveComponent("CloseBold");
        return _ctx.status === "running" ? (vue.openBlock(), vue.createBlock(_component_el_icon, {
          key: 0,
          class: "status-icon is-loading"
        }, {
          default: vue.withCtx(() => [
            vue.createVNode(_component_Loading)
          ]),
          _: 1
        })) : _ctx.status === "done" ? (vue.openBlock(), vue.createBlock(_component_el_icon, {
          key: 1,
          class: "status-icon",
          style: { "color": "#1ab059" }
        }, {
          default: vue.withCtx(() => [
            vue.createVNode(_component_Select)
          ]),
          _: 1
        })) : _ctx.status === "error" ? (vue.openBlock(), vue.createBlock(_component_el_icon, {
          key: 2,
          class: "status-icon",
          style: { "color": "#ff6464" }
        }, {
          default: vue.withCtx(() => [
            vue.createVNode(_component_CloseBold)
          ]),
          _: 1
        })) : vue.createCommentVNode("", true);
      };
    }
  });
  const TaskStatusIcon = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-2f9d6050"]]);
  const MyIconsVue = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
    __proto__: null,
    Info: InfoIcon,
    TaskStatus: TaskStatusIcon,
    Tasks: TasksIcon
  }, Symbol.toStringTag, { value: "Module" }));
  (function() {
    if (isTargetFrame()) {
      const app = vue.createApp(App);
      const pinia$1 = pinia.createPinia();
      app.use(ElementPlus);
      app.use(pinia$1);
      const logger = new Logger("main.ts");
      const cacheStore = useCacheStore();
      cacheStore.checkIfMainBLTHRunning();
      if (!cacheStore.isMainBLTHRunning) {
        logger.log("当前脚本是Main BLTH,开始存活心跳");
        cacheStore.startAliveHeartBeat();
      } else {
        logger.log("其它页面上存在正在运行的Main BLTH");
      }
      for (const [key, component] of Object.entries(ElementPlusIconsVue__namespace)) {
        app.component(key, component);
      }
      for (const [key, component] of Object.entries(MyIconsVue)) {
        app.component(key, component);
      }
      app.mount(
        (() => {
          try {
            const app2 = dce("div");
            app2.id = "BLTH";
            document.body.append(app2);
            return app2;
          } catch (e) {
            logger.error("挂载Vue app时发送错误", e);
            return "Error";
          }
        })()
      );
    }
  })();

})(Vue, Pinia, _, luxon, CryptoJS, ElementPlusIconsVue, ElementPlus, hotkeys);