CN POE Export

Export CN POE data.

Mint 2023.12.15.. Lásd a legutóbbi verzió

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

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 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.

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

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         CN POE Export
// @namespace    https://github.com/cn-poe-community/cn-poe-export-monkey
// @version      0.0.14
// @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://cdn.jsdelivr.net/npm/[email protected]/dist/translator.global.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/db.global.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/creater.global.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/pako_deflate.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js
// @require      https://cdn.jsdelivr.net/npm/[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");

})();