原神语音听书导入

从 https://bv2.firefly.matce.cn 导入原神语音用于听书

// ==UserScript==
// @name         原神语音听书导入
// @namespace    https://yfi.moe
// @version      0.1.3
// @author       Yunfi <[email protected]>
// @description  从 https://bv2.firefly.matce.cn 导入原神语音用于听书
// @license      MIT
// @icon         https://bv2.firefly.matce.cn/favicon.ico
// @match        https://bv2.firefly.matce.cn/*
// @require      https://cdn.staticfile.org/vue/3.4.21/vue.global.prod.min.js
// @grant        GM_addStyle
// ==/UserScript==

(o=>{if(typeof GM_addStyle=="function"){GM_addStyle(o);return}const e=document.createElement("style");e.textContent=o,document.head.append(e)})(" :root{font-family:Inter,Avenir,Helvetica,Arial,sans-serif;font-size:16px;line-height:24px;font-weight:400;color-scheme:light dark;color:#202020de;background-color:#fff;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}.v-a{font-weight:500;color:#646cff;text-decoration:inherit}.v-a:hover{color:#535bf2}h1{font-size:3.2em;line-height:1.1}.v-button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#f9f9f9;cursor:pointer;transition:border-color .25s}.v-button:hover{border-color:#646cff}.card{padding:2em}@media (prefers-color-scheme: dark){:root{color:#ffffffde;background-color:#0b0f19}.v-a:hover{color:#747bff}.v-button{background-color:#343434}}#iread-oc-modal[data-v-63501ad3]{position:fixed;margin:auto;border:none;border-radius:1rem;box-shadow:0 0 10px #0000001a;padding:3rem}.close-dialog[data-v-63501ad3]{position:absolute;top:.5rem;right:.5rem}.inner-modal[data-v-63501ad3]{display:flex;flex-direction:column;gap:1rem;background-color:#fff}.btn-a[data-v-63501ad3]{text-decoration:none;color:inherit;text-align:center}.show-btn[data-v-43b38518]{position:fixed;bottom:1rem;right:1rem;border-radius:9999px}.btn-card[data-v-43b38518]{position:fixed;bottom:4rem;right:1rem;display:flex;flex-direction:column;gap:1rem;padding:1rem;background-color:#fff;border-radius:1rem;box-shadow:0 0 10px #0000001a}@media (prefers-color-scheme: dark){.btn-card[data-v-43b38518]{background-color:#222}}.slide-enter-active[data-v-43b38518],.slide-leave-active[data-v-43b38518]{transition:all .15s ease-in-out}.slide-enter-from[data-v-43b38518],.slide-leave-to[data-v-43b38518]{transform:translate(100%);opacity:0} ");

(function (vue) {
  'use strict';

  function generateRandomString(digits = 32) {
    const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    let randomString = "";
    for (let i = 0; i < digits; i++) {
      const randomIndex = Math.floor(Math.random() * characters.length);
      randomString += characters[randomIndex];
    }
    return randomString;
  }
  function getConfig() {
    const selectors = [
      null,
      "#component-5 > label > div > div.wrap-inner > div > input",
      "#range_id_0",
      "#range_id_1",
      "#range_id_2",
      "#range_id_3",
      "#component-14 > label > div > div.wrap-inner > div > input",
      "#component-29 > label > input",
      "#range_id_6",
      "#range_id_5",
      null,
      "#component-8 > label > textarea",
      "#component-22 > label > textarea",
      "#range_id_4"
    ];
    let data = [];
    for (const selector of selectors) {
      data.push(
        selector ? document.querySelector(selector).value : null
      );
    }
    if (!data[1]) {
      alert("请选择角色,或者等待页面加载完全后再点击按钮");
      throw new Error("not getting data from page");
    }
    for (let i of [2, 3, 4, 5, 8, 9, 13]) {
      data[i] = parseFloat(data[i]);
    }
    data[7] = false;
    return {
      data,
      event_data: null,
      fn_index: 0,
      session_hash: null
    };
  }
  function copy2Clipboard(text) {
    navigator.clipboard.writeText(text).then(() => {
      alert("已复制到剪贴板");
    }).catch((error) => {
      console.error("复制到剪贴板失败", error);
    });
  }
  const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
    __name: "CopyIRead",
    setup(__props) {
      function generateIReadConfig() {
        const originConfig = getConfig();
        originConfig.data[0] = "%@";
        const body = JSON.stringify(originConfig);
        const process = `@dyn:
p=def:"|'|\\n @=>;
txt=keyword.jxd_executeRegexRules:p;
format('${body}',txt)`;
        const iReadTemplate = {
          _ClassName: "JxdAdvCustomTTS",
          _TTSConfigID: generateRandomString(),
          maxWordCount: "200",
          ttsConfigGroup: "☁️",
          ttsHandles: [
            {
              processType: 1,
              maxPageCount: 1,
              nextPageForGetMedthod: 1,
              forGetMethod: 0,
              requestByWebView: 0,
              nextPageParams: {},
              url: "https://bv2.firefly.matce.cn/run/predict",
              parser: {
                audioUrl: '@str:"https://bv2.firefly.matce.cn/file={{@json:data[1].name}}"'
              },
              httpConfigs: {
                useCookies: 1,
                headers: {
                  "Content-Type": "application/json"
                },
                customFormatParams: "params[data]"
              },
              params: {
                data: process
              }
            },
            {
              maxPageCount: 1,
              nextPageForGetMedthod: 1,
              requestByWebView: 0,
              forGetMethod: 1,
              processType: 1,
              params: {},
              nextPageParams: {},
              url: "@json:audioUrl",
              parser: {
                playData: "ResponseData"
              },
              httpConfigs: {
                useCookies: 1,
                headers: {}
              }
            }
          ],
          _TTSName: "☁️ - MHY " + originConfig.data[1]
        };
        return iReadTemplate;
      }
      function copyIRead() {
        const iReadConfig = generateIReadConfig();
        copy2Clipboard(JSON.stringify(iReadConfig));
      }
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock("div", null, [
          vue.createElementVNode("button", {
            onClick: copyIRead,
            class: "v-button"
          }, "复制爱阅记配置")
        ]);
      };
    }
  });
  const _sfc_main$3 = {
    name: "MingcuteCloseLine"
  };
  const _export_sfc = (sfc, props) => {
    const target = sfc.__vccOpts || sfc;
    for (const [key, val] of props) {
      target[key] = val;
    }
    return target;
  };
  const _hoisted_1$2 = {
    xmlns: "http://www.w3.org/2000/svg",
    width: "1em",
    height: "1em",
    viewBox: "0 0 24 24"
  };
  const _hoisted_2$1 = /* @__PURE__ */ vue.createElementVNode("g", {
    fill: "none",
    fillRule: "evenodd"
  }, [
    /* @__PURE__ */ vue.createElementVNode("path", { d: "M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035c-.01-.004-.019-.001-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427c-.002-.01-.009-.017-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093c.012.004.023 0 .029-.008l.004-.014l-.034-.614c-.003-.012-.01-.02-.02-.022m-.715.002a.023.023 0 0 0-.027.006l-.006.014l-.034.614c0 .012.007.02.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" }),
    /* @__PURE__ */ vue.createElementVNode("path", {
      fill: "#888888",
      d: "m12 13.414l5.657 5.657a1 1 0 0 0 1.414-1.414L13.414 12l5.657-5.657a1 1 0 0 0-1.414-1.414L12 10.586L6.343 4.929A1 1 0 0 0 4.93 6.343L10.586 12l-5.657 5.657a1 1 0 1 0 1.414 1.414z"
    })
  ], -1);
  const _hoisted_3$1 = [
    _hoisted_2$1
  ];
  function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
    return vue.openBlock(), vue.createElementBlock("svg", _hoisted_1$2, _hoisted_3$1);
  }
  const MingcuteCloseLine = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render]]);
  const _withScopeId = (n) => (vue.pushScopeId("data-v-63501ad3"), n = n(), vue.popScopeId(), n);
  const _hoisted_1$1 = { id: "iread-oc-modal" };
  const _hoisted_2 = { class: "inner-modal" };
  const _hoisted_3 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("h5", { style: { "font-size": "large", "margin": "0.5rem auto" } }, " 爱阅记一键导入 ", -1));
  const _hoisted_4 = ["href"];
  const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
    __name: "OneClickIRead",
    setup(__props) {
      const ocURL = vue.ref("");
      function closeModal() {
        const modal = document.getElementById(
          "iread-oc-modal"
        );
        if (modal)
          modal.close();
      }
      function getUrl() {
        const { data } = getConfig();
        if (!data)
          throw new Error("No data in config");
        data[0] = "%@";
        const dataUrl = `${BACKEND_URL}/api/gvits/ireadnote?data=${encodeURIComponent(
        JSON.stringify(data)
      )}`;
        const importUrl = `iReadNote://import/itts=${dataUrl}`;
        return importUrl;
      }
      function openModal() {
        const modal = document.getElementById(
          "iread-oc-modal"
        );
        if (modal)
          modal.showModal();
        ocURL.value = getUrl();
      }
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
          vue.createElementVNode("dialog", _hoisted_1$1, [
            vue.createVNode(MingcuteCloseLine, {
              onClick: closeModal,
              class: "close-dialog"
            }),
            vue.createElementVNode("div", _hoisted_2, [
              _hoisted_3,
              vue.createElementVNode("a", {
                href: ocURL.value,
                class: "v-button btn-a",
                target: "_blank"
              }, "直接导入", 8, _hoisted_4),
              vue.createElementVNode("button", {
                onClick: _cache[0] || (_cache[0] = ($event) => vue.unref(copy2Clipboard)(ocURL.value)),
                class: "v-button"
              }, " 复制链接 ")
            ])
          ]),
          vue.createElementVNode("div", null, [
            vue.createElementVNode("button", {
              onClick: openModal,
              class: "v-button"
            }, "爱阅记一键导入")
          ])
        ], 64);
      };
    }
  });
  const OneClickIRead = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-63501ad3"]]);
  const _hoisted_1 = {
    key: 0,
    class: "btn-card"
  };
  const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
    __name: "BtnCard",
    setup(__props) {
      const showCard = vue.ref(false);
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
          vue.createElementVNode("button", {
            onClick: _cache[0] || (_cache[0] = ($event) => showCard.value = !showCard.value),
            class: "show-btn v-button"
          }, "听书导入"),
          vue.createVNode(vue.Transition, { name: "slide" }, {
            default: vue.withCtx(() => [
              showCard.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
                vue.createVNode(_sfc_main$4),
                vue.createVNode(OneClickIRead)
              ])) : vue.createCommentVNode("", true)
            ]),
            _: 1
          })
        ], 64);
      };
    }
  });
  const BtnCard = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-43b38518"]]);
  const _sfc_main = /* @__PURE__ */ vue.defineComponent({
    __name: "App",
    setup(__props) {
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createBlock(BtnCard);
      };
    }
  });
  vue.createApp(_sfc_main).mount(
    (() => {
      const app = document.createElement("div");
      document.body.append(app);
      return app;
    })()
  );
  const BACKEND_URL = "https://tts.api.yfi.moe";

})(Vue);