// ==UserScript==
// @name CN POE Export
// @namespace https://github.com/cn-poe-community/cn-poe-export-monkey
// @version 0.0.2
// @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/cn-poe-translator/dist/translator.global.js
// @require https://unpkg.com/cn-poe-export-db/dist/db.global.js
// @require https://unpkg.com/pob-building-creater/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{\r\n position: fixed;\r\n bottom: 20px;\r\n left: 10px;\r\n z-index: 99999;\r\n}\n.line-container[data-v-49ca4dbb] {\r\n display: flex;\r\n margin: 3px 0;\r\n min-height: 25px;\n}\n.line-container select[data-v-49ca4dbb] {\r\n min-height: 25px;\r\n margin-right: 4px;\r\n min-width: 100px;\n}\n.line-container input[data-v-49ca4dbb] {\r\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_49ca4dbb_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-49ca4dbb"), 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 pattern = new RegExp("/account/view-profile/([^/?]+)");
let match = pattern.exec(window.location.href);
if (match) {
return decodeURI(match[1]);
}
return "";
}
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-49ca4dbb"]]);
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");
})();