CN POE Export

Export CN POE data.

Устаревшая версия за 11.06.2023. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         CN POE Export
// @namespace    https://github.com/cn-poe-community/cn-poe-export-monkey
// @version      0.0.3
// @description  Export CN POE data.
// @author       me1ting
// @match        https://poe.game.qq.com/my-account
// @match        https://poe.game.qq.com/account/view-profile/*
// @match        https://poe.game.qq.com/forum
// @icon         https://poecdn.game.qq.com/gen/image/WzI1LDE0LHsiZiI6IjJESXRlbXMvQ3VycmVuY3kvU2NvdXRpbmdSZXBvcnQiLCJ3IjoxLCJoIjoxLCJzY2FsZSI6MX1d/584635f3c8/ScoutingReport.png
// @require      https://unpkg.com/[email protected]/dist/translator.global.js
// @require      https://unpkg.com/[email protected]/dist/db.global.js
// @require      https://unpkg.com/[email protected]/dist/creater.global.js
// @require      https://unpkg.com/[email protected]/dist/pako_deflate.min.js
// @require      https://unpkg.com/[email protected]/dist/axios.min.js
// @require      https://unpkg.com/[email protected]/dist/vue.global.prod.js
// @grant        none
// @license      MIT
// ==/UserScript==

(function(){
const {computed, ref, reactive, onMounted, openBlock, createElementBlock, Fragment, createElementVNode, withDirectives, vModelText, unref, renderList, toDisplayString, vModelSelect, createCommentVNode, pushScopeId, popScopeId, createBlock, createApp } = Vue;

(function() {
  "use strict";
  try {
    if (typeof document != "undefined") {
      var elementStyle = document.createElement("style");
      elementStyle.appendChild(document.createTextNode("#exportContainer {\n    position: fixed;\n    bottom: 20px;\n    left: 10px;\n    z-index: 99999;\n}\n\n.line-container[data-v-69f05dbf] {\n  display: flex;\n  margin: 3px 0;\n  min-height: 25px;\n}\n.line-container select[data-v-69f05dbf] {\n  min-height: 25px;\n  margin-right: 4px;\n  min-width: 100px;\n}\n.line-container input[data-v-69f05dbf] {\n  margin-right: 4px;\n}"));
      document.head.appendChild(elementStyle);
    }
  } catch (e) {
    console.error("vite-plugin-css-injected-by-js", e);
  }
})();
(function polyfill() {
  const relList = document.createElement("link").relList;
  if (relList && relList.supports && relList.supports("modulepreload")) {
    return;
  }
  for (const link of document.querySelectorAll('link[rel="modulepreload"]')) {
    processPreload(link);
  }
  new MutationObserver((mutations) => {
    for (const mutation of mutations) {
      if (mutation.type !== "childList") {
        continue;
      }
      for (const node of mutation.addedNodes) {
        if (node.tagName === "LINK" && node.rel === "modulepreload")
          processPreload(node);
      }
    }
  }).observe(document, { childList: true, subtree: true });
  function getFetchOpts(link) {
    const fetchOpts = {};
    if (link.integrity)
      fetchOpts.integrity = link.integrity;
    if (link.referrerPolicy)
      fetchOpts.referrerPolicy = link.referrerPolicy;
    if (link.crossOrigin === "use-credentials")
      fetchOpts.credentials = "include";
    else if (link.crossOrigin === "anonymous")
      fetchOpts.credentials = "omit";
    else
      fetchOpts.credentials = "same-origin";
    return fetchOpts;
  }
  function processPreload(link) {
    if (link.ep)
      return;
    link.ep = true;
    const fetchOpts = getFetchOpts(link);
    fetch(link.href, fetchOpts);
  }
})();
const main = "";
const Panel_vue_vue_type_style_index_0_scoped_69f05dbf_lang = "";
const _export_sfc = (sfc, props) => {
  const target = sfc.__vccOpts || sfc;
  for (const [key, val] of props) {
    target[key] = val;
  }
  return target;
};
const _withScopeId = (n) => (pushScopeId("data-v-69f05dbf"), n = n(), popScopeId(), n);
const _hoisted_1 = { class: "line-container" };
const _hoisted_2 = ["disabled"];
const _hoisted_3 = { class: "line-container" };
const _hoisted_4 = { key: 0 };
const _hoisted_5 = ["value"];
const _hoisted_6 = ["value"];
const _hoisted_7 = ["disabled"];
const _hoisted_8 = { key: 1 };
const _hoisted_9 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ createElementVNode("select", { disabled: "" }, null, -1));
const _hoisted_10 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ createElementVNode("select", { disabled: "" }, null, -1));
const _hoisted_11 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ createElementVNode("button", { disabled: "" }, "导出", -1));
const _hoisted_12 = [
  _hoisted_9,
  _hoisted_10,
  _hoisted_11
];
const _hoisted_13 = { class: "line-container" };
const _hoisted_14 = ["value"];
const _hoisted_15 = ["disabled"];
const realm = "pc";
const _sfc_main$1 = {
  __name: "Panel",
  setup(__props) {
    const accountName = ref("");
    const characters = ref([]);
    const leagues = ref([]);
    const leagueMap = ref(/* @__PURE__ */ new Map());
    const currLeague = ref("");
    const currCharacters = ref([]);
    const currCharacter = ref("");
    const buildingCode = ref("");
    const state = reactive({
      accountName,
      realm,
      characters,
      leagues,
      leagueMap,
      currLeague,
      currCharacters,
      currCharacter,
      buildingCode
    });
    const getCharactersReady = computed(() => {
      return Boolean(state.accountName);
    });
    const selectReady = computed(() => {
      return state.characters.length > 0;
    });
    const exportReady = computed(() => {
      return state.characters.length > 0 && Boolean(state.currCharacter);
    });
    function selectNewLeague() {
      state.currCharacters = state.leagueMap.get(state.currLeague);
      state.currCharacter = state.currCharacters[0].name;
    }
    function getCharacters() {
      const url = "/character-window/get-characters";
      const realm2 = state.realm;
      const accountName2 = state.accountName;
      let form = new URLSearchParams();
      form.append("accountName", accountName2);
      form.append("realm", realm2);
      state.currLeague = "";
      state.currCharacter = "";
      axios.post(url, form).then((res) => {
        const characters2 = res.data;
        state.characters = characters2;
        let leagueMap2 = /* @__PURE__ */ new Map();
        for (const character of characters2) {
          const leagueName = character.league;
          let list = leagueMap2.get(leagueName);
          if (list === void 0) {
            list = [];
            leagueMap2.set(leagueName, list);
          }
          list.push(character);
        }
        state.leagueMap = leagueMap2;
        const leagues2 = Array.from(leagueMap2.keys());
        state.leagues = leagues2;
        if (leagues2.length > 0) {
          state.currLeague = leagues2[0];
          selectNewLeague();
        }
      }).catch((err) => {
        state.leagues = [];
        state.characters = [];
        console.log(err);
        alert(err);
      });
    }
    async function getItems() {
      const url = "/character-window/get-items";
      const realm2 = state.realm;
      const accountName2 = state.accountName;
      const character = state.currCharacter;
      let form = new URLSearchParams();
      form.append("accountName", accountName2);
      form.append("realm", realm2);
      form.append("character", character);
      const res = await axios.post(url, form);
      return res.data;
    }
    async function getPassiveSkills() {
      const url = "/character-window/get-passive-skills";
      const realm2 = state.realm;
      const accountName2 = state.accountName;
      const character = state.currCharacter;
      let params = new URLSearchParams();
      params.append("accountName", accountName2);
      params.append("realm", realm2);
      params.append("character", character);
      const res = await axios.get(url, { params });
      return res.data;
    }
    const factory = CnPoeTranslator.newBasicTranslatorFactory(CnPoeExportDb);
    const jsonTranslator = factory.getJsonTranslator();
    async function exportBuilding() {
      let items;
      let passiveSkills;
      try {
        items = await getItems();
        passiveSkills = await getPassiveSkills();
      } catch (err) {
        alert(`加载角色数据失败: ${err}`);
      }
      jsonTranslator.translateItems(items);
      jsonTranslator.translatePassiveSkills(passiveSkills);
      const building = BuildingCreater.transform(items, passiveSkills);
      const compressed = window.pako.deflate(building.toString());
      const code = btoa(String.fromCharCode.apply(null, compressed)).replaceAll("+", "-").replaceAll("/", "_");
      state.buildingCode = code;
    }
    function copyBuildingCode() {
      navigator.clipboard.writeText(state.buildingCode);
    }
    function getInitialAccountName() {
      let accountName2 = getAccountNameFromProfileLink(window.location.href);
      if (accountName2 !== null) {
        return accountName2;
      }
      const profileLinkNode = document.querySelector("#statusBar .profile-link a");
      if (profileLinkNode !== null) {
        accountName2 = getAccountNameFromProfileLink(profileLinkNode.href);
        if (accountName2 !== null) {
          return accountName2;
        }
      }
      return "";
    }
    const pattern = new RegExp("/account/view-profile/([^/?]+)");
    function getAccountNameFromProfileLink(link) {
      const match = pattern.exec(link);
      if (match) {
        return decodeURI(match[1]);
      }
      return null;
    }
    onMounted(() => {
      state.accountName = getInitialAccountName();
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(Fragment, null, [
        createElementVNode("span", _hoisted_1, [
          withDirectives(createElementVNode("input", {
            type: "text",
            placeholder: "输入论坛账户名",
            maxlength: "50",
            "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => state.accountName = $event)
          }, null, 512), [
            [
              vModelText,
              state.accountName,
              void 0,
              { trim: true }
            ]
          ]),
          createElementVNode("button", {
            onClick: getCharacters,
            disabled: !getCharactersReady.value
          }, "开始", 8, _hoisted_2)
        ]),
        createElementVNode("span", _hoisted_3, [
          selectReady.value ? (openBlock(), createElementBlock("div", _hoisted_4, [
            selectReady.value ? withDirectives((openBlock(), createElementBlock("select", {
              key: 0,
              "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => state.currLeague = $event),
              onChange: selectNewLeague
            }, [
              (openBlock(true), createElementBlock(Fragment, null, renderList(leagues.value, (item) => {
                return openBlock(), createElementBlock("option", {
                  key: item,
                  value: item
                }, toDisplayString(item), 9, _hoisted_5);
              }), 128))
            ], 544)), [
              [vModelSelect, state.currLeague]
            ]) : createCommentVNode("", true),
            selectReady.value ? withDirectives((openBlock(), createElementBlock("select", {
              key: 1,
              "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => state.currCharacter = $event)
            }, [
              (openBlock(true), createElementBlock(Fragment, null, renderList(state.currCharacters, (item) => {
                return openBlock(), createElementBlock("option", {
                  key: item.name,
                  value: item.name
                }, toDisplayString(item.name) + "," + toDisplayString(item.level) + "," + toDisplayString(item.class), 9, _hoisted_6);
              }), 128))
            ], 512)), [
              [vModelSelect, state.currCharacter]
            ]) : createCommentVNode("", true),
            selectReady.value ? (openBlock(), createElementBlock("button", {
              key: 2,
              disabled: !exportReady.value,
              onClick: exportBuilding
            }, "导出", 8, _hoisted_7)) : createCommentVNode("", true)
          ])) : (openBlock(), createElementBlock("div", _hoisted_8, _hoisted_12))
        ]),
        createElementVNode("span", _hoisted_13, [
          createElementVNode("input", {
            disabled: "",
            maxlength: "50",
            value: state.buildingCode
          }, null, 8, _hoisted_14),
          createElementVNode("button", {
            onClick: copyBuildingCode,
            disabled: !state.buildingCode
          }, "复制", 8, _hoisted_15)
        ])
      ], 64);
    };
  }
};
const Panel = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-69f05dbf"]]);
const _sfc_main = {
  __name: "Exporter",
  setup(__props) {
    return (_ctx, _cache) => {
      return openBlock(), createBlock(Panel);
    };
  }
};
const container = document.createElement("div");
container.id = "exportContainer";
document.body.appendChild(container);
createApp(_sfc_main).mount("#exportContainer");

})();