// ==UserScript==
// @name Magic Way Idle
// @namespace http://tampermonkey.net/
// @version 1.0.10.2
// @description 法师助手
// @icon https://www.milkywayidle.com/favicon.svg
// @match https://www.milkywayidle.com/*
// @match https://test.milkywayidle.com/*
// @run-at document-start
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_notification
// @grant GM_xmlhttpRequest
// @require https://cdnjs.cloudflare.com/ajax/libs/mathjs/12.4.2/math.js
// @downloadURL none
// ==/UserScript==
(function () {
//法师排行榜
const secureData = {
app_id: "cli_a66edef774b8d00d",
secret: "RfrFWOp2N4o83FOuNGF6vfIqSAf10W6h",
baseToken: "PtCAbTAR5aI1YxsdKhic5VnPnFb",
tableID: "tblhiqRHvAtx7Rba",
qqshow:"tblaYrzLPpqJz5bX"
};
//开启死亡报警
let isNotifyDeath=true;
let tenant_access_token = "";
let isUsingLocalMarketJson = false;
const MARKET_JSON_LOCAL_BACKUP = `{"time":1720276202,"market":{"Amber":{"ask":6400,"bid":6200},"Amethyst":{"ask":64000,"bid":62000},"Apple":{"ask":5,"bid":4},"Apple Gummy":{"ask":11,"bid":-1},"Apple Yogurt":{"ask":275,"bid":110},"Aqua Arrow":{"ask":13500,"bid":10000},"Aqua Essence":{"ask":23,"bid":18},"Arabica Coffee Bean":{"ask":135,"bid":130},"Arcane Bow":{"ask":265000,"bid":120000},"Arcane Crossbow":{"ask":285000,"bid":260000},"Arcane Fire Staff":{"ask":185000,"bid":155000},"Arcane Log":{"ask":270,"bid":255},"Arcane Lumber":{"ask":960,"bid":900},"Arcane Nature Staff":{"ask":220000,"bid":120000},"Arcane Water Staff":{"ask":120000,"bid":105000},"Artisan Tea":{"ask":740,"bid":540},"Attack Coffee":{"ask":500,"bid":380},"Azure Boots":{"ask":21000,"bid":1200},"Azure Brush":{"ask":35000,"bid":2100},"Azure Buckler":{"ask":15500,"bid":1800},"Azure Bulwark":{"ask":35000,"bid":-1},"Azure Cheese":{"ask":360,"bid":340},"Azure Chisel":{"ask":25000,"bid":-1},"Azure Enhancer":{"ask":23500,"bid":-1},"Azure Gauntlets":{"ask":21000,"bid":-1},"Azure Hammer":{"ask":33000,"bid":6000},"Azure Hatchet":{"ask":30000,"bid":2100},"Azure Helmet":{"ask":23500,"bid":1450},"Azure Mace":{"ask":36000,"bid":-1},"Azure Milk":{"ask":110,"bid":94},"Azure Needle":{"ask":32000,"bid":-1},"Azure Plate Body":{"ask":35000,"bid":-1},"Azure Plate Legs":{"ask":28500,"bid":2100},"Azure Pot":{"ask":29500,"bid":-1},"Azure Shears":{"ask":50000,"bid":-1},"Azure Spatula":{"ask":28000,"bid":-1},"Azure Spear":{"ask":36000,"bid":20000},"Azure Sword":{"ask":36000,"bid":-1},"Bamboo Boots":{"ask":11000,"bid":-1},"Bamboo Branch":{"ask":30,"bid":16},"Bamboo Fabric":{"ask":270,"bid":235},"Bamboo Gloves":{"ask":14500,"bid":-1},"Bamboo Hat":{"ask":18500,"bid":5400},"Bamboo Robe Bottoms":{"ask":23000,"bid":-1},"Bamboo Robe Top":{"ask":24000,"bid":15000},"Bear Essence":{"ask":68,"bid":62},"Beast Boots":{"ask":52000,"bid":-1},"Beast Bracers":{"ask":48000,"bid":17000},"Beast Chaps":{"ask":98000,"bid":76000},"Beast Hide":{"ask":21,"bid":20},"Beast Hood":{"ask":62000,"bid":40000},"Beast Leather":{"ask":520,"bid":460},"Beast Tunic":{"ask":84000,"bid":70000},"Berserk":{"ask":430000,"bid":370000},"Birch Bow":{"ask":13000,"bid":-1},"Birch Crossbow":{"ask":17000,"bid":-1},"Birch Fire Staff":{"ask":15000,"bid":-1},"Birch Log":{"ask":56,"bid":48},"Birch Lumber":{"ask":360,"bid":195},"Birch Nature Staff":{"ask":15500,"bid":2200},"Birch Water Staff":{"ask":26500,"bid":760},"Black Bear Fluff":{"ask":44000,"bid":43000},"Black Bear Shoes":{"ask":235000,"bid":62000},"Black Tea Leaf":{"ask":20,"bid":18},"Blackberry":{"ask":45,"bid":42},"Blackberry Cake":{"ask":295,"bid":225},"Blackberry Donut":{"ask":255,"bid":180},"Blessed Tea":{"ask":490,"bid":350},"Blueberry":{"ask":28,"bid":25},"Blueberry Cake":{"ask":390,"bid":96},"Blueberry Donut":{"ask":380,"bid":72},"Brewing Tea":{"ask":240,"bid":105},"Burble Brush":{"ask":56000,"bid":-1},"Burble Buckler":{"ask":49000,"bid":-1},"Burble Bulwark":{"ask":33000,"bid":-1},"Burble Chisel":{"ask":54000,"bid":-1},"Burble Enhancer":{"ask":48000,"bid":20000},"Burble Gauntlets":{"ask":46000,"bid":-1},"Burble Hatchet":{"ask":49000,"bid":-1},"Burble Helmet":{"ask":46000,"bid":-1},"Burble Mace":{"ask":56000,"bid":15000},"Burble Needle":{"ask":44000,"bid":18000},"Burble Plate Body":{"ask":50000,"bid":17000},"Burble Pot":{"ask":45000,"bid":21000},"Burble Shears":{"ask":52000,"bid":-1},"Burble Spatula":{"ask":40000,"bid":5200},"Burble Sword":{"ask":52000,"bid":-1},"Burble Tea Leaf":{"ask":66,"bid":50},"Cedar Bow":{"ask":42000,"bid":3500},"Cedar Fire Staff":{"ask":41000,"bid":3200},"Cedar Log":{"ask":92,"bid":72},"Cedar Lumber":{"ask":450,"bid":360},"Cedar Water Staff":{"ask":42000,"bid":4300},"Centaur Boots":{"ask":980000,"bid":700000},"Centaur Hoof":{"ask":125000,"bid":120000},"Cheese Boots":{"ask":2400,"bid":66},"Cheese Brush":{"ask":4400,"bid":125},"Cheese Buckler":{"ask":-1,"bid":400},"Cheese Chisel":{"ask":3500,"bid":-1},"Cheese Enhancer":{"ask":3300,"bid":1000},"Cheese Gauntlets":{"ask":2400,"bid":66},"Cheese Hammer":{"ask":4200,"bid":-1},"Cheese Helmet":{"ask":2650,"bid":100},"Cheese Mace":{"ask":5800,"bid":150},"Cheese Plate Body":{"ask":2550,"bid":155},"Cheese Plate Legs":{"ask":-1,"bid":1000},"Cheese Pot":{"ask":4000,"bid":2000},"Cheese Spatula":{"ask":4100,"bid":115},"Cheese Spear":{"ask":14000,"bid":300},"Cheese Sword":{"ask":5000,"bid":300},"Cleave":{"ask":135000,"bid":100000},"Cocoon":{"ask":145,"bid":120},"Coin":{"ask":-1,"bid":-1},"Cotton":{"ask":30,"bid":15},"Cotton Boots":{"ask":440,"bid":-1},"Cotton Fabric":{"ask":74,"bid":31},"Cotton Hat":{"ask":1100,"bid":-1},"Cotton Robe Bottoms":{"ask":1900,"bid":-1},"Cotton Robe Top":{"ask":2700,"bid":-1},"Crab Pincer":{"ask":8600,"bid":8200},"Crafting Tea":{"ask":360,"bid":185},"Crimson Boots":{"ask":72000,"bid":18000},"Crimson Buckler":{"ask":105000,"bid":-1},"Crimson Bulwark":{"ask":49000,"bid":-1},"Crimson Cheese":{"ask":430,"bid":390},"Crimson Enhancer":{"ask":54000,"bid":43000},"Crimson Gauntlets":{"ask":52000,"bid":15000},"Crimson Hammer":{"ask":66000,"bid":40000},"Crimson Helmet":{"ask":84000,"bid":36000},"Crimson Mace":{"ask":96000,"bid":-1},"Crimson Milk":{"ask":110,"bid":96},"Crimson Plate Body":{"ask":60000,"bid":-1},"Crimson Plate Legs":{"ask":78000,"bid":22000},"Crimson Pot":{"ask":50000,"bid":-1},"Crimson Spatula":{"ask":68000,"bid":-1},"Crimson Spear":{"ask":-1,"bid":58000},"Crimson Sword":{"ask":-1,"bid":72000},"Crushed Amber":{"ask":390,"bid":300},"Crushed Amethyst":{"ask":4000,"bid":3000},"Crushed Garnet":{"ask":1300,"bid":840},"Crushed Moonstone":{"ask":2850,"bid":1000},"Crushed Pearl":{"ask":920,"bid":800},"Cupcake":{"ask":180,"bid":20},"Donut":{"ask":155,"bid":17},"Dragon Fruit":{"ask":115,"bid":110},"Dragon Fruit Gummy":{"ask":500,"bid":440},"Earrings Of Armor":{"ask":2250000,"bid":-1},"Earrings Of Gathering":{"ask":4900000,"bid":-1},"Earrings Of Regeneration":{"ask":4400000,"bid":3600000},"Earrings Of Resistance":{"ask":880000,"bid":30000},"Efficiency Tea":{"ask":540,"bid":470},"Elemental Affinity":{"ask":580000,"bid":560000},"Emp Tea Leaf":{"ask":86,"bid":84},"Enhancing Tea":{"ask":370,"bid":170},"Excelsa Coffee Bean":{"ask":320,"bid":285},"Eyessence":{"ask":76,"bid":70},"Fieriosa Coffee Bean":{"ask":360,"bid":340},"Fireball":{"ask":16500,"bid":16000},"Flame Arrow":{"ask":13000,"bid":7800},"Flame Blast":{"ask":160000,"bid":150000},"Flaming Cloth":{"ask":29000,"bid":20000},"Flaming Robe Top":{"ask":98000,"bid":60000},"Flax":{"ask":49,"bid":44},"Foraging Tea":{"ask":215,"bid":10},"Garnet":{"ask":14000,"bid":13500},"Gathering Tea":{"ask":340,"bid":295},"Giant Pouch":{"ask":6400000,"bid":5600000},"Ginkgo Bow":{"ask":100000,"bid":20000},"Ginkgo Crossbow":{"ask":110000,"bid":-1},"Ginkgo Log":{"ask":58,"bid":48},"Ginkgo Lumber":{"ask":370,"bid":265},"Ginkgo Nature Staff":{"ask":88000,"bid":-1},"Gobo Boomstick":{"ask":21000,"bid":-1},"Gobo Boots":{"ask":22000,"bid":-1},"Gobo Bracers":{"ask":18500,"bid":8600},"Gobo Essence":{"ask":155,"bid":105},"Gobo Hide":{"ask":21,"bid":15},"Gobo Hood":{"ask":15000,"bid":10000},"Gobo Shooter":{"ask":25500,"bid":23000},"Gobo Slasher":{"ask":24500,"bid":-1},"Gobo Smasher":{"ask":20000,"bid":-1},"Gobo Tunic":{"ask":31000,"bid":17000},"Goggles":{"ask":46000,"bid":37000},"Golem Essence":{"ask":230,"bid":180},"Granite Bludgeon":{"ask":42000000,"bid":1000000},"Green Tea Leaf":{"ask":14,"bid":11},"Grizzly Bear Fluff":{"ask":50000,"bid":43000},"Gummy":{"ask":175,"bid":20},"Heal":{"ask":210000,"bid":195000},"Holy Boots":{"ask":120000,"bid":-1},"Holy Buckler":{"ask":240000,"bid":-1},"Holy Bulwark":{"ask":140000,"bid":-1},"Holy Cheese":{"ask":960,"bid":920},"Holy Enhancer":{"ask":205000,"bid":185000},"Holy Gauntlets":{"ask":220000,"bid":-1},"Holy Hammer":{"ask":235000,"bid":185000},"Holy Helmet":{"ask":360000,"bid":70000},"Holy Mace":{"ask":285000,"bid":-1},"Holy Milk":{"ask":300,"bid":270},"Holy Plate Body":{"ask":390000,"bid":-1},"Holy Plate Legs":{"ask":295000,"bid":165000},"Holy Pot":{"ask":210000,"bid":160000},"Holy Spatula":{"ask":220000,"bid":185000},"Holy Spear":{"ask":200000,"bid":80000},"Holy Sword":{"ask":290000,"bid":245000},"Icy Cloth":{"ask":21000,"bid":12000},"Icy Robe Bottoms":{"ask":100000,"bid":41000},"Icy Robe Top":{"ask":100000,"bid":60000},"Jade":{"ask":19000,"bid":16000},"Jungle Essence":{"ask":74,"bid":66},"Large Artisan's Crate":{"ask":-1,"bid":-1},"Large Pouch":{"ask":800000,"bid":500000},"Large Treasure Chest":{"ask":-1,"bid":-1},"Liberica Coffee Bean":{"ask":285,"bid":255},"Linen Boots":{"ask":7400,"bid":600},"Linen Gloves":{"ask":9800,"bid":580},"Linen Hat":{"ask":9400,"bid":-1},"Linen Robe Bottoms":{"ask":16500,"bid":1100},"Living Granite":{"ask":1400000,"bid":820000},"Log":{"ask":29,"bid":25},"Lucky Coffee":{"ask":1250,"bid":880},"Magic Coffee":{"ask":400,"bid":370},"Magnet":{"ask":90000,"bid":74000},"Magnifying Glass":{"ask":680000,"bid":620000},"Maim":{"ask":130000,"bid":115000},"Marsberry":{"ask":35,"bid":31},"Marsberry Donut":{"ask":420,"bid":340},"Medium Artisan's Crate":{"ask":-1,"bid":-1},"Medium Meteorite Cache":{"ask":-1,"bid":-1},"Medium Treasure Chest":{"ask":-1,"bid":-1},"Milk":{"ask":32,"bid":28},"Milking Tea":{"ask":430,"bid":100},"Minor Heal":{"ask":17000,"bid":14000},"Mooberry":{"ask":64,"bid":52},"Mooberry Cake":{"ask":440,"bid":285},"Mooberry Donut":{"ask":330,"bid":145},"Moonstone":{"ask":21000,"bid":20000},"Necklace Of Efficiency":{"ask":6800000,"bid":-1},"Necklace Of Wisdom":{"ask":7200000,"bid":6200000},"Orange Gummy":{"ask":39,"bid":25},"Orange Yogurt":{"ask":410,"bid":175},"Panda Gloves":{"ask":-1,"bid":-1},"Peach":{"ask":31,"bid":19},"Peach Gummy":{"ask":210,"bid":170},"Pearl":{"ask":14000,"bid":13500},"Pierce":{"ask":-1,"bid":-1},"Pincer Gloves":{"ask":52000,"bid":10000},"Plum":{"ask":88,"bid":58},"Plum Yogurt":{"ask":340,"bid":290},"Poke":{"ask":7200,"bid":7000},"Power Coffee":{"ask":700,"bid":420},"Precision":{"ask":13000,"bid":9600},"Purpleheart Bow":{"ask":60000,"bid":-1},"Purpleheart Crossbow":{"ask":50000,"bid":35000},"Purpleheart Fire Staff":{"ask":100000,"bid":6800},"Purpleheart Lumber":{"ask":340,"bid":310},"Purpleheart Nature Staff":{"ask":68000,"bid":12500},"Purpleheart Water Staff":{"ask":76000,"bid":7400},"Quick Shot":{"ask":2900,"bid":2300},"Radiant Fabric":{"ask":820,"bid":800},"Radiant Fiber":{"ask":150,"bid":125},"Radiant Gloves":{"ask":86000,"bid":54000},"Radiant Robe Bottoms":{"ask":250000,"bid":165000},"Radiant Robe Top":{"ask":255000,"bid":120000},"Rain Of Arrows":{"ask":165000,"bid":135000},"Rainbow Brush":{"ask":110000,"bid":72000},"Rainbow Buckler":{"ask":84000,"bid":-1},"Rainbow Bulwark":{"ask":140000,"bid":-1},"Rainbow Chisel":{"ask":110000,"bid":30000},"Rainbow Enhancer":{"ask":105000,"bid":32000},"Rainbow Gauntlets":{"ask":84000,"bid":-1},"Rainbow Hatchet":{"ask":96000,"bid":30000},"Rainbow Helmet":{"ask":74000,"bid":50000},"Rainbow Mace":{"ask":125000,"bid":-1},"Rainbow Needle":{"ask":115000,"bid":30000},"Rainbow Plate Body":{"ask":170000,"bid":-1},"Rainbow Plate Legs":{"ask":-1,"bid":-1},"Rainbow Shears":{"ask":98000,"bid":60000},"Rainbow Spatula":{"ask":-1,"bid":76000},"Rainbow Spear":{"ask":125000,"bid":-1},"Ranged Coffee":{"ask":480,"bid":260},"Ranger Necklace":{"ask":7800000,"bid":5600000},"Red Tea Leaf":{"ask":58,"bid":52},"Redwood Crossbow":{"ask":130000,"bid":32000},"Redwood Fire Staff":{"ask":120000,"bid":-1},"Redwood Log":{"ask":32,"bid":27},"Redwood Nature Staff":{"ask":130000,"bid":-1},"Redwood Water Staff":{"ask":74000,"bid":-1},"Reptile Boots":{"ask":12500,"bid":580},"Reptile Chaps":{"ask":11000,"bid":1100},"Reptile Hide":{"ask":18,"bid":10},"Reptile Hood":{"ask":12000,"bid":720},"Reptile Tunic":{"ask":12500,"bid":-1},"Ring Of Armor":{"ask":2500000,"bid":1000000},"Ring Of Gathering":{"ask":-1,"bid":2000000},"Ring Of Regeneration":{"ask":4300000,"bid":2000000},"Ring Of Resistance":{"ask":1400000,"bid":30000},"Robusta Coffee Bean":{"ask":220,"bid":190},"Rough Bracers":{"ask":2650,"bid":-1},"Rough Chaps":{"ask":2200,"bid":-1},"Rough Hide":{"ask":42,"bid":35},"Rough Leather":{"ask":200,"bid":165},"Rough Tunic":{"ask":7000,"bid":-1},"Scratch":{"ask":2900,"bid":1450},"Silk Boots":{"ask":-1,"bid":8000},"Silk Fabric":{"ask":740,"bid":700},"Silk Gloves":{"ask":40000,"bid":28500},"Silk Robe Bottoms":{"ask":60000,"bid":52000},"Silk Robe Top":{"ask":96000,"bid":-1},"Smack":{"ask":4100,"bid":3900},"Small Meteorite Cache":{"ask":-1,"bid":-1},"Small Pouch":{"ask":58000,"bid":15000},"Snail Shell":{"ask":4000,"bid":3600},"Snail Shell Helmet":{"ask":6000,"bid":-1},"Snake Fang":{"ask":2100,"bid":2000},"Sorcerer Boots":{"ask":145000,"bid":70000},"Sorcerer Essence":{"ask":175,"bid":150},"Sorcerer's Sole":{"ask":64000,"bid":62000},"Spaceberry Cake":{"ask":920,"bid":900},"Spaceberry Donut":{"ask":760,"bid":700},"Spacia Coffee Bean":{"ask":720,"bid":660},"Stalactite Shard":{"ask":960000,"bid":760000},"Stalactite Spear":{"ask":-1,"bid":14000000},"Stamina Coffee":{"ask":310,"bid":275},"Star Fruit":{"ask":310,"bid":295},"Star Fruit Gummy":{"ask":700,"bid":640},"Star Fruit Yogurt":{"ask":940,"bid":900},"Strawberry Cake":{"ask":400,"bid":255},"Strawberry Donut":{"ask":260,"bid":33},"Stunning Blow":{"ask":560000,"bid":540000},"Super Attack Coffee":{"ask":1650,"bid":1450},"Super Brewing Tea":{"ask":740,"bid":165},"Super Cheesesmithing Tea":{"ask":2400,"bid":1650},"Super Crafting Tea":{"ask":2900,"bid":1550},"Super Defense Coffee":{"ask":1450,"bid":1300},"Super Enhancing Tea":{"ask":1950,"bid":520},"Super Foraging Tea":{"ask":1650,"bid":520},"Super Magic Coffee":{"ask":5400,"bid":5000},"Super Milking Tea":{"ask":2400,"bid":600},"Super Power Coffee":{"ask":2750,"bid":2450},"Super Stamina Coffee":{"ask":1800,"bid":1600},"Super Tailoring Tea":{"ask":6000,"bid":3500},"Super Woodcutting Tea":{"ask":4500,"bid":1450},"Sweep":{"ask":100000,"bid":90000},"Swiftness Coffee":{"ask":980,"bid":880},"Tailoring Tea":{"ask":250,"bid":125},"Tome Of The Elements":{"ask":160000,"bid":105000},"Toughness":{"ask":68000,"bid":25000},"Toxic Pollen":{"ask":135000,"bid":125000},"Turtle Shell Body":{"ask":17500,"bid":9000},"Turtle Shell Legs":{"ask":38000,"bid":6000},"Twilight Essence":{"ask":120,"bid":115},"Umbral Bracers":{"ask":43000,"bid":-1},"Umbral Chaps":{"ask":84000,"bid":-1},"Umbral Hide":{"ask":68,"bid":48},"Umbral Leather":{"ask":700,"bid":680},"Umbral Tunic":{"ask":115000,"bid":-1},"Vampire Fang":{"ask":430000,"bid":350000},"Vampirism":{"ask":50000,"bid":22000},"Verdant Boots":{"ask":11500,"bid":320},"Verdant Brush":{"ask":15500,"bid":5000},"Verdant Bulwark":{"ask":8000,"bid":-1},"Verdant Cheese":{"ask":270,"bid":255},"Verdant Chisel":{"ask":14500,"bid":-1},"Verdant Gauntlets":{"ask":9400,"bid":-1},"Verdant Hammer":{"ask":17500,"bid":560},"Verdant Hatchet":{"ask":14500,"bid":600},"Verdant Mace":{"ask":14500,"bid":-1},"Verdant Milk":{"ask":58,"bid":54},"Verdant Needle":{"ask":14000,"bid":-1},"Verdant Plate Legs":{"ask":13000,"bid":-1},"Verdant Pot":{"ask":14000,"bid":10000},"Verdant Shears":{"ask":13500,"bid":-1},"Verdant Spear":{"ask":14000,"bid":1450},"Verdant Sword":{"ask":15500,"bid":720},"Vision Helmet":{"ask":82000,"bid":42000},"Water Strike":{"ask":16500,"bid":16000},"Werewolf Claw":{"ask":260000,"bid":92000},"Werewolf Slasher":{"ask":5000000,"bid":-1},"Wisdom Coffee":{"ask":860,"bid":840},"Wisdom Tea":{"ask":600,"bid":500},"Wizard Necklace":{"ask":9600000,"bid":4300000},"Wooden Bow":{"ask":5000,"bid":-1},"Wooden Crossbow":{"ask":3200,"bid":-1},"Wooden Fire Staff":{"ask":3600,"bid":-1},"Wooden Water Staff":{"ask":3500,"bid":145},"Yogurt":{"ask":200,"bid":40},"Burble Boots":{"ask":38000,"bid":-1},"Burble Cheese":{"ask":330,"bid":320},"Burble Hammer":{"ask":46000,"bid":16000},"Burble Milk":{"ask":125,"bid":115},"Cedar Nature Staff":{"ask":42000,"bid":3200},"Cheese":{"ask":140,"bid":105},"Cheese Bulwark":{"ask":2250,"bid":-1},"Cheese Hatchet":{"ask":5400,"bid":-1},"Cheese Needle":{"ask":2200,"bid":-1},"Cheese Shears":{"ask":3100,"bid":-1},"Cheesesmithing Tea":{"ask":500,"bid":250},"Cooking Tea":{"ask":160,"bid":150},"Cotton Gloves":{"ask":620,"bid":-1},"Cowbell":{"ask":-1,"bid":-1},"Crimson Brush":{"ask":66000,"bid":50000},"Crimson Chisel":{"ask":74000,"bid":40000},"Crimson Hatchet":{"ask":56000,"bid":45000},"Crimson Shears":{"ask":-1,"bid":-1},"Critical Coffee":{"ask":1900,"bid":1700},"Crushed Jade":{"ask":1200,"bid":1100},"Defense Coffee":{"ask":640,"bid":340},"Dragon Fruit Yogurt":{"ask":560,"bid":500},"Flaming Robe Bottoms":{"ask":100000,"bid":40000},"Frenzy":{"ask":175000,"bid":165000},"Gobo Leather":{"ask":410,"bid":265},"Holy Chisel":{"ask":210000,"bid":185000},"Holy Hatchet":{"ask":195000,"bid":180000},"Holy Needle":{"ask":185000,"bid":165000},"Holy Shears":{"ask":200000,"bid":155000},"Ice Spear":{"ask":30000,"bid":28500},"Intelligence Coffee":{"ask":380,"bid":285},"Linen Fabric":{"ask":310,"bid":195},"Linen Robe Top":{"ask":10000,"bid":-1},"Lumber":{"ask":330,"bid":255},"Mirror Of Protection":{"ask":7800000,"bid":7400000},"Moolong Tea Leaf":{"ask":40,"bid":33},"Orange":{"ask":9,"bid":6},"Panda Fluff":{"ask":90000,"bid":56000},"Peach Yogurt":{"ask":-1,"bid":370},"Plum Gummy":{"ask":64,"bid":52},"Processing Tea":{"ask":760,"bid":600},"Purpleheart Log":{"ask":90,"bid":60},"Radiant Boots":{"ask":22500,"bid":-1},"Radiant Hat":{"ask":190000,"bid":130000},"Rainbow Boots":{"ask":98000,"bid":50000},"Rainbow Cheese":{"ask":420,"bid":390},"Rainbow Hammer":{"ask":105000,"bid":40000},"Rainbow Milk":{"ask":125,"bid":105},"Rainbow Pot":{"ask":90000,"bid":-1},"Rainbow Sword":{"ask":135000,"bid":120000},"Redwood Bow":{"ask":155000,"bid":50000},"Redwood Lumber":{"ask":235,"bid":215},"Reptile Bracers":{"ask":10500,"bid":-1},"Reptile Leather":{"ask":140,"bid":110},"Ring Of Rare Find":{"ask":3700000,"bid":3100000},"Rough Boots":{"ask":2000,"bid":-1},"Rough Hood":{"ask":2000,"bid":1200},"Shard Of Protection":{"ask":44000,"bid":42000},"Silk Hat":{"ask":62000,"bid":-1},"Small Artisan's Crate":{"ask":-1,"bid":-1},"Small Treasure Chest":{"ask":-1,"bid":-1},"Snake Fang Dirk":{"ask":10500,"bid":2500},"Spaceberry":{"ask":190,"bid":170},"Spike Shell":{"ask":360000,"bid":310000},"Star Fragment":{"ask":7000,"bid":6800},"Strawberry":{"ask":50,"bid":48},"Super Cooking Tea":{"ask":1650,"bid":800},"Super Intelligence Coffee":{"ask":2000,"bid":1750},"Super Ranged Coffee":{"ask":2450,"bid":2300},"Swamp Essence":{"ask":19,"bid":17},"Tome Of Healing":{"ask":20000,"bid":16000},"Turtle Shell":{"ask":11500,"bid":5800},"Umbral Boots":{"ask":26500,"bid":-1},"Umbral Hood":{"ask":145000,"bid":-1},"Vampire Fang Dirk":{"ask":9000000,"bid":5200000},"Verdant Buckler":{"ask":7000,"bid":600},"Verdant Enhancer":{"ask":11000,"bid":-1},"Verdant Helmet":{"ask":11000,"bid":-1},"Verdant Spatula":{"ask":12500,"bid":-1},"Vision Shield":{"ask":1150000,"bid":80000},"Wheat":{"ask":25,"bid":22},"Woodcutting Tea":{"ask":220,"bid":100},"Wooden Nature Staff":{"ask":18500,"bid":145},"Cedar Crossbow":{"ask":19500,"bid":12000},"Earrings Of Rare Find":{"ask":3500000,"bid":2900000},"Egg":{"ask":29,"bid":20},"Entangle":{"ask":2950,"bid":2000},"Fighter Necklace":{"ask":4900000,"bid":-1},"Gator Vest":{"ask":10000,"bid":7800},"Ginkgo Fire Staff":{"ask":74000,"bid":15000},"Gobo Chaps":{"ask":29500,"bid":15500},"Gobo Stabber":{"ask":20000,"bid":-1},"Gourmet Tea":{"ask":460,"bid":350},"Grizzly Bear Shoes":{"ask":580000,"bid":64000},"Holy Brush":{"ask":220000,"bid":190000},"Large Meteorite Cache":{"ask":-1,"bid":-1},"Magnetic Gloves":{"ask":640000,"bid":-1},"Marsberry Cake":{"ask":540,"bid":520},"Medium Pouch":{"ask":245000,"bid":-1},"Polar Bear Fluff":{"ask":74000,"bid":68000},"Verdant Plate Body":{"ask":14000,"bid":860},"Ginkgo Water Staff":{"ask":66000,"bid":14000},"Polar Bear Shoes":{"ask":660000,"bid":185000},"Sugar":{"ask":7,"bid":6},"Crimson Needle":{"ask":56000,"bid":40000},"Burble Plate Legs":{"ask":49000,"bid":-1},"Burble Spear":{"ask":56000,"bid":25000},"Arcane Shield":{"ask":70000,"bid":-1},"Birch Shield":{"ask":3300,"bid":490},"Cedar Shield":{"ask":50000,"bid":2000},"Ginkgo Shield":{"ask":19000,"bid":-1},"Purpleheart Shield":{"ask":14000,"bid":-1},"Redwood Shield":{"ask":39000,"bid":-1},"Sighted Bracers":{"ask":840000,"bid":640000},"Spiked Bulwark":{"ask":-1,"bid":500000},"Wooden Shield":{"ask":480,"bid":-1},"Advanced Task Ring":{"ask":-1,"bid":-1},"Basic Task Ring":{"ask":-1,"bid":-1},"Expert Task Ring":{"ask":-1,"bid":-1},"Purple's Gift":{"ask":-1,"bid":-1},"Task Crystal":{"ask":-1,"bid":-1},"Task Token":{"ask":-1,"bid":-1},"Abyssal Essence":{"ask":280,"bid":260},"Channeling Coffee":{"ask":780,"bid":700},"Chrono Gloves":{"ask":3600000,"bid":2100000},"Chrono Sphere":{"ask":360000,"bid":320000},"Collector's Boots":{"ask":1100000,"bid":640000},"Colossus Core":{"ask":600000,"bid":500000},"Colossus Plate Body":{"ask":6200000,"bid":-1},"Colossus Plate Legs":{"ask":4600000,"bid":2100000},"Demonic Core":{"ask":1150000,"bid":1100000},"Demonic Plate Body":{"ask":10000000,"bid":9200000},"Demonic Plate Legs":{"ask":9800000,"bid":7200000},"Elusiveness":{"ask":11500,"bid":7600},"Enchanted Gloves":{"ask":4500000,"bid":3500000},"Eye Of The Watcher":{"ask":400000,"bid":370000},"Eye Watch":{"ask":3900000,"bid":2800000},"Firestorm":{"ask":720000,"bid":620000},"Fluffy Red Hat":{"ask":2250000,"bid":-1},"Frost Sphere":{"ask":520000,"bid":470000},"Frost Staff":{"ask":-1,"bid":3000000},"Frost Surge":{"ask":760000,"bid":720000},"Gobo Defender":{"ask":275000,"bid":240000},"Gobo Rag":{"ask":92000,"bid":84000},"Infernal Battlestaff":{"ask":-1,"bid":21500000},"Infernal Ember":{"ask":1750000,"bid":1600000},"Luna Robe Bottoms":{"ask":2050000,"bid":800000},"Luna Robe Top":{"ask":2250000,"bid":800000},"Luna Wing":{"ask":155000,"bid":140000},"Marine Chaps":{"ask":430000,"bid":-1},"Marine Scale":{"ask":39000,"bid":31000},"Marine Tunic":{"ask":580000,"bid":-1},"Nature's Veil":{"ask":880000,"bid":740000},"Puncture":{"ask":185000,"bid":160000},"Red Chef's Hat":{"ask":1300000,"bid":1100000},"Red Panda Fluff":{"ask":145000,"bid":120000},"Revenant Anima":{"ask":700000,"bid":640000},"Revenant Chaps":{"ask":7200000,"bid":4500000},"Revenant Tunic":{"ask":9000000,"bid":4000000},"Shoebill Feather":{"ask":26000,"bid":20000},"Shoebill Shoes":{"ask":-1,"bid":-1},"Silencing Shot":{"ask":135000,"bid":120000},"Soul Fragment":{"ask":760000,"bid":580000},"Soul Hunter Crossbow":{"ask":-1,"bid":7400000},"Steady Shot":{"ask":640000,"bid":480000},"Treant Bark":{"ask":9800,"bid":8600},"Treant Shield":{"ask":32000,"bid":-1},"Vampiric Bow":{"ask":8400000,"bid":5600000},"Watchful Relic":{"ask":3900000,"bid":2700000},"Bag Of 10 Cowbells":{"ask":290000,"bid":275000},"Aqua Aura":{"ask":3200000,"bid":2450000},"Critical Aura":{"ask":9600000,"bid":5800000},"Fierce Aura":{"ask":16500000,"bid":6800000},"Flame Aura":{"ask":5200000,"bid":4200000},"Insanity":{"ask":6800000,"bid":5800000},"Invincible":{"ask":5000000,"bid":3100000},"Provoke":{"ask":245000,"bid":175000},"Quick Aid":{"ask":720000,"bid":620000},"Rejuvenate":{"ask":1250000,"bid":1100000},"Revive":{"ask":1250000,"bid":680000},"Speed Aura":{"ask":8400000,"bid":5200000},"Sylvan Aura":{"ask":6000000,"bid":4500000},"Taunt":{"ask":90000,"bid":24000},"Acrobatic Hood":{"ask":-1,"bid":35000000},"Acrobat's Ribbon":{"ask":4800000,"bid":4500000},"Bishop's Codex":{"ask":-1,"bid":-1},"Bishop's Scroll":{"ask":6800000,"bid":6600000},"Blue Key Fragment":{"ask":420000,"bid":400000},"Brown Key Fragment":{"ask":840000,"bid":740000},"Burning Key Fragment":{"ask":1800000,"bid":1700000},"Chaotic Chain":{"ask":9600000,"bid":9200000},"Chaotic Flail":{"ask":-1,"bid":145000000},"Chimerical Chest":{"ask":-1,"bid":-1},"Chimerical Essence":{"ask":1300,"bid":980},"Chimerical Key":{"ask":2300000,"bid":2150000},"Chimerical Quiver":{"ask":-1,"bid":-1},"Crippling Slash":{"ask":94000,"bid":92000},"Cursed Ball":{"ask":4000000,"bid":1550000},"Cursed Bow":{"ask":-1,"bid":9000000},"Dark Key Fragment":{"ask":2000000,"bid":1900000},"Dodocamel Gauntlets":{"ask":-1,"bid":42000000},"Dodocamel Plume":{"ask":8000000,"bid":7000000},"Earrings Of Threat":{"ask":4200000,"bid":1050000},"Enchanted Chest":{"ask":-1,"bid":-1},"Enchanted Cloak":{"ask":-1,"bid":-1},"Enchanted Essence":{"ask":3800,"bid":3600},"Enchanted Key":{"ask":5400000,"bid":5000000},"Green Key Fragment":{"ask":330000,"bid":290000},"Griffin Chaps":{"ask":7000000,"bid":-1},"Griffin Leather":{"ask":520000,"bid":330000},"Griffin Tunic":{"ask":8000000,"bid":3300000},"Impale":{"ask":17500,"bid":8000},"Jackalope Antler":{"ask":1600000,"bid":1050000},"Jackalope Staff":{"ask":-1,"bid":16500000},"Knight's Aegis":{"ask":64000000,"bid":42000000},"Knight's Ingot":{"ask":5600000,"bid":5200000},"Magician's Cloth":{"ask":8200000,"bid":7600000},"Magician's Hat":{"ask":92000000,"bid":70000000},"Mana Spring":{"ask":880000,"bid":820000},"Manticore Shield":{"ask":18000000,"bid":-1},"Manticore Sting":{"ask":1300000,"bid":1250000},"Orange Key Fragment":{"ask":380000,"bid":300000},"Penetrating Shot":{"ask":1200000,"bid":980000},"Penetrating Strike":{"ask":230000,"bid":190000},"Pestilent Shot":{"ask":96000,"bid":84000},"Purple Key Fragment":{"ask":500000,"bid":320000},"Regal Jewel":{"ask":9800000,"bid":7400000},"Regal Sword":{"ask":-1,"bid":100000000},"Ring Of Threat":{"ask":3200000,"bid":1050000},"Royal Cloth":{"ask":9800000,"bid":9000000},"Royal Fire Robe Bottoms":{"ask":-1,"bid":5200000},"Royal Fire Robe Top":{"ask":-1,"bid":5200000},"Royal Nature Robe Bottoms":{"ask":-1,"bid":10000000},"Royal Nature Robe Top":{"ask":-1,"bid":10000000},"Royal Water Robe Bottoms":{"ask":-1,"bid":-1},"Royal Water Robe Top":{"ask":-1,"bid":-1},"Sinister Cape":{"ask":-1,"bid":-1},"Sinister Chest":{"ask":-1,"bid":-1},"Sinister Essence":{"ask":1900,"bid":1850},"Sinister Key":{"ask":3700000,"bid":3500000},"Smoke Burst":{"ask":105000,"bid":100000},"Stone Key Fragment":{"ask":2100000,"bid":1750000},"Sundering Crossbow":{"ask":420000000,"bid":240000000},"Sundering Jewel":{"ask":14500000,"bid":13500000},"White Key Fragment":{"ask":1000000,"bid":940000}}}`;
const MARKET_API_URL = "https://raw.githubusercontent.com/holychikenz/MWIApi/main/medianmarket.json";
const MARKET_API_URL_BACKUP = "http://43.129.194.214:5500/apijson";
let initData_itemDetailMap = null;
let initData_actionDetailMap = null;
let initData_levelExperienceTable = null;
let autoClickTaskManagerObserver=null;
let isTaskManagerClickable=false;
let deathBattleId=-1;
let battle_player={};
let first_battle;
let isInstallEdible_Tools=false;
let playerName;
//坏了改false不修复
let isQQshowServerAlive=true;
var qqshowReplacementTargets = {};
//脚本初始化
script_init();
function script_init(){
//切换logo提示脚本已生效
try{
replaceIcon();
replaceText();
//通知权限测试
Notification.requestPermission().then(function(result) {
if (result === 'denied') {
//console.log('拒绝显示系统通知');
return;
}
if (result === 'default') {
//console.log('默认');
return;
}
//console.log('允许显示系统通知')
});
//拦截WS
}catch(err){}
hookWS();
//更新飞书Token
getTenantToken();
//获取qqshow
try{
if(isQQshowServerAlive){
if('MWIQQshow_json' in localStorage){
qqshowReplacementTargets=JSON.parse(localStorage.getItem("MWIQQshow_json"));
}
getqqshow();
}
}catch(err){}
//判断依赖:食用工具是否启动
if('Edible_Tools' in localStorage)isInstallEdible_Tools=true;
//启动自动任务排序(依赖MWItool,其实是冲突了,懒得写没装的情况)
let globalObserverConfig = { childList: true, subtree: true };
let globalObserver=new MutationObserver(function (mutationsList, observer) {
autoClickTaskManager();
if(isQQshowServerAlive)addQQshowButton();
});
globalObserver.observe(document, globalObserverConfig);
first_battle=true;
}
//改logo(脚本生效测试)
function replaceIcon() {
const targetDiv = document.querySelector('div.Header_logoContainer__1sCnZ');
const load_check=document.querySelector('div.Header_totalLevel__8LY3Q');
if (load_check && targetDiv && targetDiv.children.length > 0 && targetDiv.querySelector('svg')) {
let originalIcon = targetDiv.firstChild;
originalIcon.innerHTML =``;
}else {
setTimeout(replaceIcon, 500);
}
}
//改title(脚本生效测试)
function replaceText() {
const targetDiv = document.querySelector('div.Header_title__5Mj8z');
const load_check=document.querySelector('div.Header_totalLevel__8LY3Q');
if (load_check && targetDiv && targetDiv.children.length > 0 && targetDiv.querySelector('svg')) {
const originaltext = targetDiv.firstChild;
const newtext = document.createElement('img');
newtext.src = 'https://tupian.li/images/2024/10/03/66fd73f009f84.png';
newtext.width = '64';
newtext.height = '64';
originaltext.parentNode.replaceChild(newtext, originaltext);
}else {
setTimeout(replaceText, 500);
}
}
//拦截WS
function hookWS() {
const dataProperty = Object.getOwnPropertyDescriptor(MessageEvent.prototype, "data");
const oriGet = dataProperty.get;
dataProperty.get = hookedGet;
Object.defineProperty(MessageEvent.prototype, "data", dataProperty);
function hookedGet() {
const socket = this.currentTarget;
if (!(socket instanceof WebSocket)) {
return oriGet.call(this);
}
if (socket.url.indexOf("api.milkywayidle.com/ws") <= -1 && socket.url.indexOf("api-test.milkywayidle.com/ws") <= -1) {
return oriGet.call(this);
}
const message = oriGet.call(this);
Object.defineProperty(this, "data", { value: message });
return handleMessage(message);
}
}
//WS拦截后处理,主进程
function handleMessage(message,debug=false) {
let obj = JSON.parse(message);
if (obj && obj.type === "init_character_data") {
//切角色图标更新
playerName=obj.character.name;
replaceIcon();
replaceText();
first_battle=true;
} else if (obj && obj.type === "init_client_data") {
//初始化映射表
initData_itemDetailMap = obj.itemDetailMap;
initData_actionDetailMap = obj.actionDetailMap;
initData_levelExperienceTable = obj.levelExperienceTable;
//史黛拉战斗排行
addStellaRankButton();
}else if (obj && obj.type === "new_battle") {
//死亡报警
if(isNotifyDeath)notifyDeath(obj);
} else if (obj && obj.type === "battle_updated") {
//死亡报警
if(isNotifyDeath)notifyDeath(obj);
}else if (obj && obj.type === "profile_shared"){
//显示打造分
showBuildCost(obj);
//提交数据库
//submitPlayerInfoToDB(obj)
}else if (obj && obj.type === "market_item_order_books_updated") {
updateMarketItem(obj);
}else if (obj && obj.type === "actions_updated") {
first_battle=true;
}
//other
return message;
}
//死亡报警
function notifyDeath(obj){
if (obj && obj.type === "new_battle"){
//战斗人员信息初始化
if(first_battle){
first_battle=false;
battle_player={};
for(const key in obj.players){
battle_player[key]={
name:obj.players[key].character.name,
isalive:true
};
}
}
for(const key in obj.players){
if(obj.players[key].isActive){
battle_player[key].isalive=true;
}else{
if(battle_player[key].isalive){
showNotification(`${battle_player[key].name}死了`);
}
battle_player[key].isalive=false;
}
}
}else if (obj && obj.type === "battle_updated") {
if(obj.pMap){
for (const key in obj.pMap) {
if(obj.pMap[key].cHP==0){
if(battle_player[key].isalive){
battle_player[key].isalive=false;
showNotification(`${battle_player[key].name}死了`);
}
}else{
battle_player[key].isalive=true;
}
}
}
}
}
//提交数据库
function submitPlayerInfoToDB(obj){
try{
const profile = obj.profile;
const name = profile.sharableCharacter.name;
const guild_name = profile.guildName;
const skills = profile.characterSkills;
const birth = profile.sharableCharacter.createdAt.slice(0, 10).replace(/-/g, '/');
//console.log("Name:", name);
//console.log("Guild Name:", guild_name);
//console.log("Skills and Experience:");
const info = [name, guild_name, birth];
const skillOrder = [
"stamina",
"intelligence",
"attack",
"power",
"defense",
"ranged",
"magic",
"total_level",
];
for (let skillName of skillOrder) {
const skill = skills.find((s) => s.skillHrid.endsWith(skillName));
if (skill) {
const skillLevel = skill.level;
const skillExp = Math.round(skill.experience); // 保留经验为整数
info.push(skillLevel, skillExp);
}
}
//console.log(info.join(", "));
RecordInfo(info);
} catch (error) {
//console.error("提交数据库失败:", error);
}
}
//获取个人属性面板
function getInfoPanel(){
const selectedElement = document.querySelector(`div.SharableProfile_overviewTab__W4dCV`);
if(selectedElement){
return selectedElement
}else{
return new Promise((resolve) => {
setTimeout(() => resolve(getInfoPanel()), 500);
});
}
}
//显示打造分
async function showBuildCost(profile_shared_obj){
let text_to_show = await getBuildCost(profile_shared_obj);
let BD_cost = document.createElement('div');
BD_cost.textContent = text_to_show;
let selectedElement = await getInfoPanel();
if (selectedElement) {
let last_child=selectedElement.lastElementChild
//显示在导入按钮前
if(last_child && last_child.textContent == '获取模拟器导入数据'){
selectedElement.insertBefore(BD_cost, last_child);
}else if(selectedElement){
selectedElement.appendChild(BD_cost);
}
} else {
//console.log('个人面板未加载');
}
}
//计算打造分
async function getBuildCost(profile_shared_obj){
//返回字符串
//console.log(profile_shared_obj);
let obj=profile_shared_obj.profile;
let BD_cost=0;
BD_cost=Number(BD_cost);
//房子价值(仅战斗)
let battle_house=['dining_room', 'library', 'dojo', 'gym', 'armory', 'archery_range', 'mystical_study'];
//1-8级房仅金币价格(累计)
//每级价格参考:https://docs.google.com/spreadsheets/d/1SmXDs-UNhEWKb29biBfA1mfO2CkSpxyHEkAlfTYPS50/edit?gid=991886661#gid=991886661
const house_cost_map = {
0: 0,
1: 0.5,
2: 2.5,
3: 7.5,
4: 19.5,
5: 44.5,
6: 94.5,
7: 184.5,
8: 344.5
};
for (const key in obj.characterHouseRoomMap) {
if (battle_house.some(house => obj.characterHouseRoomMap[key].houseRoomHrid.includes(house))) {
BD_cost+=Number(house_cost_map[obj.characterHouseRoomMap[key].level]);
}
}
if(obj.hideWearableItems)return `打造分:${BD_cost}(仅房子)`;
console.log('房屋分:'+BD_cost);
//技能价值
try {
const skillBid = await calculateSkill(profile_shared_obj);
BD_cost += Number(skillBid);
console.log('技能分:'+skillBid);
} catch (error) {
//console.error('Error in calculate skill:', error);
}
//装备价值
try {
const networthBid = await calculateEquipment(profile_shared_obj);
BD_cost += Number(networthBid);
console.log('装备分:'+networthBid);
} catch (error) {
//console.error('Error in calculateEquipmen:', error);
}
//保留2位小数
BD_cost = BD_cost.toString().match(/^\d+(?:\.\d{0,2})?/)[0];
return "打造分:" + BD_cost;
}
//技能价格计算
async function calculateSkill(profile_shared_obj){
const marketAPIJson = await fetchMarketJSON();
if (!marketAPIJson) {
return 0;
}
let obj=profile_shared_obj.profile;
let exp_50_skill=['poke','scratch','smack','quick_shot','water_strike','fireball','entangle','minor_heal'];
const getNeedBooksToLevel = (targetLevel, abilityPerBookExp) => {
const needExp = initData_levelExperienceTable[targetLevel];
let needBooks = needExp / abilityPerBookExp;
needBooks += 1;
return needBooks.toFixed(1);
};
//技能净值
let networthAsk = 0;
let networthBid = 0;
obj.equippedAbilities.forEach(item => {
let numBooks=0;
if(exp_50_skill.some(skill => item.abilityHrid.includes(skill))){
numBooks = getNeedBooksToLevel(item.level, 50);
}else{
numBooks = getNeedBooksToLevel(item.level, 500);
}
const itemName = initData_itemDetailMap[item.abilityHrid.replace('/abilities/', '/items/')].name;
const marketPrices = marketAPIJson.market[itemName];
if (marketPrices) {
networthAsk += numBooks * (marketPrices.ask > 0 ? marketPrices.ask : 0);
networthBid += numBooks * (marketPrices.bid > 0 ? marketPrices.bid : 0);
} else {
// console.error("calculateNetworth cannot find price of " + itemName);
}
//console.log(`技能:${itemName},价值${numBooks * (marketPrices.bid > 0 ? marketPrices.bid : 0)}`)
});
//填单保守估计
networthBid/=1000000;
return networthBid;
}
//装备价格计算
async function calculateEquipment(profile_shared_obj) {
const marketAPIJson = await fetchMarketJSON();
if (!marketAPIJson) {
return 0;
}
let obj=profile_shared_obj.profile;
//装备净值
let networthAsk = 0;
let networthBid = 0;
for (const key in obj.wearableItemMap) {
let item=obj.wearableItemMap[key];
const enhanceLevel = obj.wearableItemMap[key].enhancementLevel;
const itemName = initData_itemDetailMap[obj.wearableItemMap[key].itemHrid].name;
const marketPrices = marketAPIJson.market[itemName];
if (enhanceLevel && enhanceLevel > 1) {
input_data.item_hrid = item.itemHrid;
input_data.stop_at = enhanceLevel;
const best = await findBestEnhanceStrat(input_data);
let totalCost = best?.totalCost;
totalCost = totalCost ? Math.round(totalCost) : 0;
networthAsk += item.count * (totalCost > 0 ? totalCost : 0);
networthBid += item.count * (totalCost > 0 ? totalCost : 0);
} else if (marketPrices) {
networthAsk += item.count * (marketPrices.ask > 0 ? marketPrices.ask : 0);
networthBid += item.count * (marketPrices.bid > 0 ? marketPrices.bid : 0);
} else {
// console.error("calculateNetworth cannot find price of " + itemName);
}
}
//填单保守估计
networthBid/=1000000;
return networthBid;
}
// begin::装备强化依赖函数
// Source: MWITools 13.5
async function findBestEnhanceStrat(input_data) {
const price_data = await fetchMarketJSON();
if (!price_data || !price_data.market) {
console.error("findBestEnhanceStrat fetchMarketJSON null");
return [];
}
const allResults = [];
for (let protect_at = 2; protect_at <= input_data.stop_at; protect_at++) {
const simResult = Enhancelate(input_data, protect_at);
const costs = getCosts(input_data.item_hrid, price_data);
const totalCost = costs.baseCost + costs.minProtectionCost * simResult.protect_count + costs.perActionCost * simResult.actions;
const r = {};
r.protect_at = protect_at;
r.protect_count = simResult.protect_count;
r.simResult = simResult;
r.costs = costs;
r.totalCost = totalCost;
allResults.push(r);
}
let best = null;
for (const r of allResults) {
if (best === null || r.totalCost < best.totalCost) {
best = r;
}
}
return best;
}
// Source: https://doh-nuts.github.io/Enhancelator/
function Enhancelate(input_data, protect_at) {
const success_rate = [
50, //+1
45, //+2
45, //+3
40, //+4
40, //+5
40, //+6
35, //+7
35, //+8
35, //+9
35, //+10
30, //+11
30, //+12
30, //+13
30, //+14
30, //+15
30, //+16
30, //+17
30, //+18
30, //+19
30, //+20
];
// 物品等级
const itemLevel = initData_itemDetailMap[input_data.item_hrid].itemLevel;
// 总强化buff
let total_bonus = null;
const effective_level = input_data.enhancing_level + (input_data.tea_enhancing ? 3 : 0) + (input_data.tea_super_enhancing ? 6 : 0);
if (effective_level >= itemLevel) {
total_bonus = 1 + (0.05 * (effective_level + input_data.laboratory_level - itemLevel) + input_data.enhancer_bonus) / 100;
} else {
total_bonus = 1 - 0.5 * (1 - effective_level / itemLevel) + (0.05 * input_data.laboratory_level + input_data.enhancer_bonus) / 100;
}
// 模拟
let markov = math.zeros(20, 20);
for (let i = 0; i < input_data.stop_at; i++) {
const success_chance = (success_rate[i] / 100.0) * total_bonus;
const destination = i >= protect_at ? i - 1 : 0;
if (input_data.tea_blessed) {
markov.set([i, i + 2], success_chance * 0.01);
markov.set([i, i + 1], success_chance * 0.99);
markov.set([i, destination], 1 - success_chance);
} else {
markov.set([i, i + 1], success_chance);
markov.set([i, destination], 1.0 - success_chance);
}
}
markov.set([input_data.stop_at, input_data.stop_at], 1.0);
let Q = markov.subset(math.index(math.range(0, input_data.stop_at), math.range(0, input_data.stop_at)));
const M = math.inv(math.subtract(math.identity(input_data.stop_at), Q));
const attemptsArray = M.subset(math.index(math.range(0, 1), math.range(0, input_data.stop_at)));
const attempts = math.flatten(math.row(attemptsArray, 0).valueOf()).reduce((a, b) => a + b, 0);
const protectAttempts = M.subset(math.index(math.range(0, 1), math.range(protect_at, input_data.stop_at)));
const protectAttemptsArray = typeof protectAttempts === "number" ? [protectAttempts] : math.flatten(math.row(protectAttempts, 0).valueOf());
const protects = protectAttemptsArray.map((a, i) => a * markov.get([i + protect_at, i + protect_at - 1])).reduce((a, b) => a + b, 0);
// 动作时间
const perActionTimeSec = (
12 /
(1 +
(input_data.enhancing_level > itemLevel
? (effective_level + input_data.laboratory_level - itemLevel + input_data.glove_bonus) / 100
: (input_data.laboratory_level + input_data.glove_bonus) / 100))
).toFixed(2);
const result = {};
result.actions = attempts;
result.protect_count = protects;
result.totalActionTimeSec = perActionTimeSec * attempts;
result.totalActionTimeStr = timeReadable(result.totalActionTimeSec);
return result;
}
function timeReadable(sec) {
if (sec >= 86400) {
return Number(sec / 86400).toFixed(1) + " 天";
}
const d = new Date(Math.round(sec * 1000));
function pad(i) {
return ("0" + i).slice(-2);
}
let str = d.getUTCHours() + "h " + pad(d.getUTCMinutes()) + "m " + pad(d.getUTCSeconds()) + "s";
return str;
}
// 自定义强化模拟输入参数
let input_data = {
item_hrid: null,
stop_at: null,
enhancing_level: 95, // 人物 Enhancing 技能等级
laboratory_level: 4, // 房子等级
enhancer_bonus: 4.64, // 工具提高成功率,0级=3.6,5级=4.03,10级=4.64
glove_bonus: 11.2, // 手套提高强化速度,0级=10,5级=11.2,10级=12.9
tea_enhancing: false, // 强化茶
tea_super_enhancing: true, // 超级强化茶
tea_blessed: true, // 祝福茶
priceAskBidRatio: 1, // 取市场卖单价买单价比例,1=只用卖单价,0=只用买单价
};
function getCosts(hrid, price_data) {
const itemDetailObj = initData_itemDetailMap[hrid];
// +0本体成本
const baseItemProductionCost = getItemProductionCost(itemDetailObj.name, price_data);
const baseItemMarketPrice = getItemMarketPrice(hrid, price_data);
let baseCost = baseItemProductionCost;
if (!baseCost || baseCost < 0 || (baseItemMarketPrice > 0 && baseItemMarketPrice < baseCost)) {
baseCost = baseItemMarketPrice;
}
// 保护成本
let minProtectionPrice = null;
let minProtectionHrid = null;
let protect_item_hrids =
itemDetailObj.protectionItemHrids == null
? [hrid, "/items/mirror_of_protection"]
: [hrid, "/items/mirror_of_protection"].concat(itemDetailObj.protectionItemHrids);
protect_item_hrids.forEach((protection_hrid, i) => {
const this_cost = getItemMarketPrice(protection_hrid, price_data);
if (i === 0) {
minProtectionPrice = this_cost;
minProtectionHrid = protection_hrid;
} else {
if (this_cost > 0 && (minProtectionPrice < 0 || this_cost < minProtectionPrice)) {
minProtectionPrice = this_cost;
minProtectionHrid = protection_hrid;
}
}
});
// 强化材料成本
const needMap = {};
let totalNeedPrice = 0;
for (const need of itemDetailObj.enhancementCosts) {
const price = getItemMarketPrice(need.itemHrid, price_data);
totalNeedPrice += price * need.count;
if (!need.itemHrid.includes("/coin")) {
needMap[initData_itemDetailMap[need.itemHrid].name] = price;
}
}
return {
baseCost: baseCost,
minProtectionCost: minProtectionPrice,
perActionCost: totalNeedPrice,
choiceOfProtection: minProtectionHrid,
needMap: needMap,
};
}
function getItemMarketPrice(hrid, price_data) {
const fullName = initData_itemDetailMap[hrid].name;
const item_price_data = price_data.market[fullName];
if (!item_price_data) {
return 0;
}
let final_cost = item_price_data.ask * input_data.priceAskBidRatio + item_price_data.bid * (1 - input_data.priceAskBidRatio);
return final_cost;
}
function getItemProductionCost(itemName, jsonObj) {
const actionHrid = getActionHridFromItemName(itemName);
if (!actionHrid || !initData_actionDetailMap[actionHrid]) {
return -1;
}
const inputItems = JSON.parse(JSON.stringify(initData_actionDetailMap[actionHrid].inputItems));
const upgradedFromItemHrid = initData_actionDetailMap[actionHrid]?.upgradeItemHrid;
if (upgradedFromItemHrid) {
inputItems.push({ itemHrid: upgradedFromItemHrid, count: 1 });
}
let totalAskPrice = 0;
let totalBidPrice = 0;
for (let item of inputItems) {
const itemDetail = initData_itemDetailMap[item.itemHrid];
if (!itemDetail) {
return -1;
}
let itemAskPrice = jsonObj?.market[itemDetail.name]?.ask;
let itemBidPrice = jsonObj?.market[itemDetail.name]?.bid;
if (itemAskPrice === undefined || itemAskPrice === -1) {
if (itemBidPrice === undefined || itemBidPrice === -1) {
return -1; // Ask和Bid价都没有,返回-1
}
itemAskPrice = itemBidPrice;
}
if (itemBidPrice === undefined || itemBidPrice === -1) {
itemBidPrice = itemAskPrice;
}
totalAskPrice += itemAskPrice * item.count;
totalBidPrice += itemBidPrice * item.count;
}
return totalAskPrice * input_data.priceAskBidRatio + totalBidPrice * (1 - input_data.priceAskBidRatio);
}
function getActionHridFromItemName(name) {
let newName = name.replace("Milk", "Cow");
newName = newName.replace("Log", "Tree");
newName = newName.replace("Cowing", "Milking");
newName = newName.replace("Rainbow Cow", "Unicow");
if (!initData_actionDetailMap) {
//console.error("getActionHridFromItemName no initData_actionDetailMap: " + name);
return null;
}
for (const action of Object.values(initData_actionDetailMap)) {
if (action.name === newName) {
return action.hrid;
}
}
return null;
}
//end::装备强化依赖函数
//正式通知
function showNotification(text_to_print){
let notification = new Notification('Magic Way Idle', {
body: text_to_print,
});
}
//用户记录
async function RecordInfo(info) {
let [
姓名,
公会名,
生日,
耐力等级,
耐力经验,
智力等级,
智力经验,
攻击等级,
攻击经验,
力量等级,
力量经验,
防御等级,
防御经验,
远程等级,
远程经验,
魔法等级,
魔法经验,
总等级,
总经验
] = info;
const req_url = `https://open.feishu.cn/open-apis/bitable/v1/apps/${secureData.baseToken}/tables/${secureData.tableID}/records`;
const post_header = {
Authorization: `Bearer ${tenant_access_token}`,
"Content-Type": "application/json",
};
// Build record payload
const payload = {
fields: {
姓名: 姓名,
公会名: 公会名,
生日: 生日,
耐力等级: 耐力等级,
耐力经验: 耐力经验,
智力等级: 智力等级,
智力经验: 智力经验,
攻击等级: 攻击等级,
攻击经验: 攻击经验,
力量等级: 力量等级,
力量经验: 力量经验,
防御等级: 防御等级,
防御经验: 防御经验,
远程等级: 远程等级,
远程经验: 远程经验,
魔法等级: 魔法等级,
魔法经验: 魔法经验,
总等级: 总等级,
总经验: 总经验
},
};
//console.log("???:",JSON.stringify(payload));
// Send POST request to record information
GM_xmlhttpRequest({
method: "POST",
url: req_url,
headers: post_header,
data: JSON.stringify(payload),
onload: function (response) {
// console.log("记录信息响应:", response.responseText);
try {
const responseData = JSON.parse(response.responseText);
if (responseData.code === 0) {
// console.log("成功记录信息:", responseData.data);
} else {
// console.error("记录信息失败或数据格式不正确");
}
} catch (error) {
// console.error("解析记录信息响应时出错:", error);
}
},
onerror: function (error) {
//console.error("Error recording information:", error);
},
});
}
//获取飞书 tenant_access_token
async function getTenantToken() {
const req_url = `https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal`;
const payload = {
app_id: secureData.app_id,
app_secret: secureData.secret,
};
await post_api(req_url, payload);
}
//提交飞书 POST request
async function post_api(req_url, payload) {
const payloadJson = JSON.stringify(payload);
let post_header = {
"Content-Type": "application/json",
};
// Send the POST request
GM_xmlhttpRequest({
method: "POST",
url: req_url,
headers: post_header,
data: payloadJson,
onload: function (response) {
console.log(req_url);
console.log("响应:", response.responseText);
try {
const responseData = JSON.parse(response.responseText);
if (responseData.tenant_access_token) {
tenant_access_token = responseData.tenant_access_token;
// Store tenant_access_token securely
console.log("获取的 tenant_access_token:", tenant_access_token);
} else {
console.error("未能获取 tenant_access_token");
}
} catch (error) {
console.error("解析响应时出错:", error);
}
},
onerror: function (error) {
console.error("Error fetching data:", error);
},
});
}
//市场API
async function fetchMarketJSON(forceFetch = false) {
let sendRequest = GM.xmlHttpRequest || GM_xmlhttpRequest;
if (typeof sendRequest != 'function') {
//console.error("fetchMarketJSON null function");
isUsingLocalMarketJson = true;
const jsonStr = MARKET_JSON_LOCAL_BACKUP;
const jsonObj = JSON.parse(jsonStr);
if (jsonObj && jsonObj.time && jsonObj.market) {
jsonObj.market.Coin.ask = 1;
jsonObj.market.Coin.bid = 1;
//console.log(jsonObj);
localStorage.setItem("MWITools_marketAPI_timestamp", Date.now());
localStorage.setItem("MWITools_marketAPI_json", JSON.stringify(jsonObj));
return jsonObj;
}
}
if (
!forceFetch &&
localStorage.getItem("MWITools_marketAPI_timestamp") &&
Date.now() - localStorage.getItem("MWITools_marketAPI_timestamp") < 900000
) {
return JSON.parse(localStorage.getItem("MWITools_marketAPI_json"));
}
//console.log("fetchMarketJSON fetch github start");
let jsonStr = null;
jsonStr = await new Promise((resolve, reject) => {
sendRequest({
url: MARKET_API_URL,
method: "GET",
synchronous: true,
timeout: 5000,
onload: async (response) => {
if (response.status == 200) {
//console.log("fetchMarketJSON fetch github success 200");
resolve(response.responseText);
} else {
//console.error("fetchMarketJSON fetch github onload with HTTP status failure " + response.status);
resolve(null);
}
},
onabort: () => {
//console.error("fetchMarketJSON fetch github onabort");
resolve(null);
},
onerror: () => {
//console.error("fetchMarketJSON fetch github onerror");
resolve(null);
},
ontimeout: () => {
//console.error("fetchMarketJSON fetch github ontimeout");
resolve(null);
},
});
});
if (jsonStr === null) {
//console.log("fetchMarketJSON fetch backup start");
jsonStr = await new Promise((resolve, reject) => {
sendRequest({
url: MARKET_API_URL_BACKUP,
method: "GET",
synchronous: true,
timeout: 5000,
onload: async (response) => {
if (response.status == 200) {
//console.log("fetchMarketJSON fetch backup success 200");
resolve(response.responseText);
} else {
//console.error("fetchMarketJSON fetch backup onload with HTTP status failure " + response.status);
resolve(null);
}
},
onabort: () => {
//console.error("fetchMarketJSON fetch backup onabort");
resolve(null);
},
onerror: () => {
//console.error("fetchMarketJSON fetch backup onerror");
resolve(null);
},
ontimeout: () => {
console.error("fetchMarketJSON fetch backup ontimeout");
resolve(null);
},
});
});
}
if (!jsonStr) {
//console.error("fetchMarketJSON network error, using local version");
isUsingLocalMarketJson = true;
jsonStr = MARKET_JSON_LOCAL_BACKUP;
} else {
isUsingLocalMarketJson = false;
}
const jsonObj = JSON.parse(jsonStr);
if (jsonObj && jsonObj.time && jsonObj.market) {
jsonObj.market.Coin.ask = 1;
jsonObj.market.Coin.bid = 1;
//console.log(jsonObj);
localStorage.setItem("MWITools_marketAPI_timestamp", Date.now());
localStorage.setItem("MWITools_marketAPI_json", JSON.stringify(jsonObj));
return jsonObj;
}
//console.error("MWITools: fetchMarketJSON JSON.parse error");
localStorage.setItem("MWITools_marketAPI_timestamp", 0);
localStorage.setItem("MWITools_marketAPI_json", "");
return null;
}
//自动点任务排序
// Source: MWI TaskManager 0.2
const taskBattleIndex = 99; //Battle at bottom
const taskOrderIndex = {
Milking: 1,
Foraging: 2,
Woodcutting: 3,
Cheesesmithing: 4,
Crafting: 5,
Tailoring: 6,
Cooking: 7,
Brewing: 8,
Enhancing: 9,
Defeat: 99, //Battle at bottom
};
/* 支持修改版汉化插件 */
function getOriTextFromElement(elem) {
if (!elem) {
//console.error("getTextFromElement null elem");
return "";
}
const translatedfrom = elem.getAttribute("script_translatedfrom");
if (translatedfrom) {
return translatedfrom;
}
return elem.textContent;
}
/* 兼容MWITools地图编号 */
function getMapIndexFromElement(elem) {
var node = elem.querySelector("span.script_taskMapIndex");
if (!node) {
return -1;
}
return Number(node.textContent.replace(/\D/ig, ""));
}
function getTaskOrderIndexByTaskName(taskName) {
var taskType = -1;
if (/^(Defeat)( [\S ]+)$/.test(taskName)) {
taskType = taskBattleIndex; //Battle at bottom
} else if (/^(.+) - .+$/.test(taskName)) {
let res = /^(.+) - .+$/.exec(taskName);
if (res[1] in taskOrderIndex) {
taskType = taskOrderIndex[res[1]];
}
}
//if (taskType == -1) console.log(taskName, taskType);
return taskType;
}
function compareFn(a, b) {
var a_name = getOriTextFromElement(a.querySelector("div.RandomTask_name__1hl1b"));
var b_name = getOriTextFromElement(b.querySelector("div.RandomTask_name__1hl1b"));
var a_index = getTaskOrderIndexByTaskName(a_name);
var b_index = getTaskOrderIndexByTaskName(b_name);
if (a_index === taskBattleIndex && b_index === taskBattleIndex) {
var a_MapIndex = getMapIndexFromElement(a);
var b_MapIndex = getMapIndexFromElement(b);
if (a_MapIndex != b_MapIndex) {
return (a_MapIndex > b_MapIndex ? 1 : -1);
}
}
if (a_index == b_index) {
return a_name == b_name ? 0
: (a_name > b_name ? 1 : -1);
}
return a_index > b_index ? 1 : -1;
}
function autoClickTaskManager() {
const isInTask = document.querySelector("div.TasksPanel_taskSlotCount__nfhgS");
const isAllTaskAdd = document.querySelector("div.TasksPanel_taskList__2xh4k");
const isIndexAdd = document.querySelector("span.script_taskMapIndex");
if (isInTask){
//进入任务界面
if(isAllTaskAdd&&isTaskManagerClickable&&isIndexAdd){
isTaskManagerClickable=false;
const list = document.querySelector("div.TasksPanel_taskList__2xh4k");
const nodes = [...list.querySelectorAll("div.RandomTask_randomTask__3B9fA")];
nodes.sort(compareFn).forEach(node => list.appendChild(node));
//依赖满足计算收益
if(isInstallEdible_Tools){
function convertKEndStringToNumber(str) {
if (str.endsWith('K')||str.endsWith('k')) {
return Number(str.slice(0, -1)) * 1000;
} else {
return Number(str);
}
}
let tokenValue=Number(getTaskTokenValue());
nodes.forEach(function (node) {
let reward=node.querySelector("div.RandomTask_rewards__YZk7D");
let coin=convertKEndStringToNumber(reward.querySelectorAll("div.Item_count__1HVvv")[0].innerText);
let token=Number(reward.querySelectorAll("div.Item_count__1HVvv")[1].innerText);
let newDiv = document.createElement("div");
newDiv.textContent = "期望收益: "+(addCommasToNumber((coin+token*tokenValue).toFixed(0)));
newDiv.style.color = 'gold';
node.querySelector("div.RandomTask_action__3eC6o").appendChild(newDiv);
});
}
}
}else{
//其他界面或没加载按钮
isTaskManagerClickable=true;
}
}
function addCommasToNumber(number) {
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
//单个任务代币价值
function getTaskTokenValue(){
if(!isInstallEdible_Tools)return -1;
let obj=JSON.parse(localStorage.getItem("Edible_Tools"));
let value=obj.Chest_Drop_Data["Large Meteorite Cache"].期望产出Bid/30.0+obj.Chest_Drop_Data["Purple's Gift"].期望产出Bid/50.0;
return value;
}
function updateMarketItem(obj){
let item_name=initData_itemDetailMap[obj.marketItemOrderBooks.itemHrid].name;
let ask=-1;
let bid=-1;
if(obj.marketItemOrderBooks.orderBooks[0].asks.length>0){
ask=obj.marketItemOrderBooks.orderBooks[0].asks[0].price;
}
if(obj.marketItemOrderBooks.orderBooks[0].bids.length>0){
bid=obj.marketItemOrderBooks.orderBooks[0].bids[0].price;
}
let jsonObj = JSON.parse(localStorage.getItem("MWITools_marketAPI_json"));
if(jsonObj.market[item_name]){
jsonObj.market[item_name].ask=ask;
jsonObj.market[item_name].bid=bid;
}
localStorage.setItem("MWITools_marketAPI_json", JSON.stringify(jsonObj));
}
//史黛拉战斗排行
function addStellaRankButton() {
const waitForNavi = () => {
const targetNode = document.querySelector("div.NavigationBar_minorNavigationLinks__dbxh7"); // 确认这个选择器是否适合你的环境
const navigationLinks = document.querySelectorAll('div.NavigationBar_minorNavigationLink__31K7Y');
let toolLink;
for (let link of navigationLinks) {
if (link.textContent.includes('插件设置')||link.textContent.includes('Script settings"')) {
toolLink = link;
break;
}
}
if (targetNode&&toolLink) {
let statsButton = document.createElement("div");
statsButton.setAttribute("class", "NavigationBar_minorNavigationLink__31K7Y");
statsButton.style.color = toolLink.style.color;
statsButton.innerHTML = "战斗排行榜";
statsButton.addEventListener("click", () => {
window.open("https://test-ctmd6jnzo6t9.feishu.cn/share/base/view/shrcnn0tLPS2k7Y506iRAYZoLUh", "_blank");
});
// 将按钮添加到目标节点
targetNode.insertBefore(statsButton, toolLink.nextSibling);
} else {
setTimeout(addStellaRankButton, 200);
}
};
waitForNavi(); // 开始等待目标节点出现
}
//追踪设置,添加头像设置栏
function addQQshowButton() {
const targetNode = document.querySelector("div.SettingsPanel_infoGrid__2nh1u");
const isqqshowFlagExist = document.querySelector("div.qqshow");
if(targetNode&&!isqqshowFlagExist){
const nameColor=targetNode.querySelectorAll("div.SettingsPanel_value__2nsKD")[2];
let qqshowtitlediv = document.createElement("div");
let qqshowdiv = document.createElement("div");
let qqshowdivflag = document.createElement("div");
qqshowtitlediv.setAttribute("class", "SettingsPanel_label__24LRD");
qqshowtitlediv.innerHTML="更新QQshow";
qqshowdiv.setAttribute("class", "SettingsPanel_value__2nsKD");
qqshowdiv.style=nameColor.style;
qqshowdivflag.setAttribute("class", "qqshow");
let qqshowURLInput = document.createElement("input");
qqshowURLInput.type = "text";
qqshowURLInput.setAttribute("class", "qqshowURLInput");
qqshowURLInput.placeholder = "图床url/提交空白视为删除";
let qqshowSubmitButton = document.createElement("button");
qqshowSubmitButton.setAttribute("class", "Button_button__1Fe9z");
qqshowSubmitButton.textContent = "提交";
qqshowSubmitButton.addEventListener("click", qqshowSubmit);
qqshowdiv.appendChild(qqshowdivflag);
qqshowdiv.appendChild(qqshowURLInput);
qqshowdiv.appendChild(qqshowSubmitButton);
let readmetitlediv = document.createElement("div");
let readme = document.createElement("div");
readmetitlediv.setAttribute("class", "SettingsPanel_label__24LRD");
readme.setAttribute("class", "SettingsPanel_value__2nsKD");
readme.innerHTML="先去tupian.li等图床上传图片,再提交url。
直接提交空白将删除QQ秀。刷新后生效。"
nameColor.parentNode.insertBefore(readme, nameColor.nextSibling);
nameColor.parentNode.insertBefore(readmetitlediv, nameColor.nextSibling);
nameColor.parentNode.insertBefore(qqshowdiv, nameColor.nextSibling);
nameColor.parentNode.insertBefore(qqshowtitlediv, nameColor.nextSibling);
}
}
function qqshowSubmit(){
let qqshowURLInput=document.querySelector("input.qqshowURLInput");
let url=qqshowURLInput.value
function isValidURL(str) {
try {
new URL(str);
return true;
} catch (err) {
return false;
}
}
if(url==''){
showToast("已删除,刷新生效");
deleteqqshow();
}else if(isValidURL(url)){
showToast("已提交,刷新生效");
updateqqshow(url);
}else{
showToast("url不合法");
}
}
async function getRecordid(name){
const query_url =`https://open.feishu.cn/open-apis/bitable/v1/apps/${secureData.baseToken}/tables/${secureData.qqshow}/records/search`;
const post_header_query = {
Authorization: `Bearer ${tenant_access_token}`,
};
const payload = {
filter:{
conjunction: "and",
conditions:[{
"field_name": "player",
"operator": "is",
"value": [
name
]
}]
},
automatic_fields: true,
};
const payloadJson = JSON.stringify(payload);
let record_id;
try{
await new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'POST',
url: query_url,
headers: post_header_query,
data: payloadJson,
onload: function (response) {
try {
const data = JSON.parse(response.responseText);
record_id=data?.data?.items[0]?.record_id;
resolve();
} catch (jsonError) {
console.error('查询qqshow错误:', jsonError);
reject(jsonError);
}
},
onerror: function (error) {
console.error('查询qqshow错误:', error);
reject(error);
}
});
});
}catch(err){}
return record_id;
}
function updateqqshow(url){
getRecordid(playerName).then((record_id) => {
if(record_id){
//更新
const query_url =`https://open.feishu.cn/open-apis/bitable/v1/apps/${secureData.baseToken}/tables/${secureData.qqshow}/records/${record_id}`;
const post_header_query = {
Authorization: `Bearer ${tenant_access_token}`,
};
return new Promise((resolve, reject) => {
const payload = {
fields:{
url:{
text: url,
link: url
}
}
};
const payloadJson = JSON.stringify(payload);
GM_xmlhttpRequest({
method: 'PUT',
url: query_url,
headers: post_header_query,
data: payloadJson,
onload: function (response) {
try {
resolve();
} catch (jsonError) {
console.error('Error parsing JSON:', jsonError);
reject(jsonError);
}
},
onerror: function (error) {
console.error('Error fetching sheets:', error);
reject(error);
}
});
});
}else{
//新增
const query_url =`https://open.feishu.cn/open-apis/bitable/v1/apps/${secureData.baseToken}/tables/${secureData.qqshow}/records`;
const post_header_query = {
Authorization: `Bearer ${tenant_access_token}`,
};
return new Promise((resolve, reject) => {
const payload = {
fields:{
player:playerName,
url:{
text: url,
link: url
}
}
};
const payloadJson = JSON.stringify(payload);
GM_xmlhttpRequest({
method: 'POST',
url: query_url,
headers: post_header_query,
data: payloadJson,
onload: function (response) {
try {
resolve();
} catch (jsonError) {
console.error('Error parsing JSON:', jsonError);
reject(jsonError);
}
},
onerror: function (error) {
console.error('Error fetching sheets:', error);
reject(error);
}
});
});
}
});
}
function deleteqqshow(){
getRecordid(playerName).then((record_id) => {
if(record_id){
const query_url =`https://open.feishu.cn/open-apis/bitable/v1/apps/${secureData.baseToken}/tables/${secureData.qqshow}/records/${record_id}`;
const post_header_query = {
Authorization: `Bearer ${tenant_access_token}`,
};
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'DELETE',
url: query_url,
headers: post_header_query,
onload: function (response) {
try {
resolve();
} catch (jsonError) {
console.error('Error parsing JSON:', jsonError);
reject(jsonError);
}
},
onerror: function (error) {
console.error('Error fetching sheets:', error);
reject(error);
}
});
});
}
});
}
function getqqshow(){
if(tenant_access_token!=""){
const query_url =`https://open.feishu.cn/open-apis/bitable/v1/apps/${secureData.baseToken}/tables/${secureData.qqshow}/records`;
const post_header_query = {
Authorization: `Bearer ${tenant_access_token}`,
};
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: query_url,
headers: post_header_query,
onload: function (response) {
try {
const data = JSON.parse(response.responseText);
qqshowReplacementTargets={};
data.data.items.forEach((item) => {
qqshowReplacementTargets[item.fields.player] =item.fields.url.text;
});
localStorage.setItem("MWIQQshow_timestamp", Date.now());
localStorage.setItem("MWIQQshow_json",JSON.stringify(qqshowReplacementTargets));
resolve();
} catch (jsonError) {
console.error('Error parsing JSON:', jsonError);
reject(jsonError);
}
},
onerror: function (error) {
console.error('Error fetching sheets:', error);
reject(error);
}
});
});
}else{
setTimeout(getqqshow, 200);
}
}
// Source: MWI玩家图标替换
// author: Ak4r1 ChatGpt Stella bot7420
function replaceIconsIn(node) {
const iconElements = node.querySelectorAll(`div.FullAvatar_fullAvatar__3RB2h`);
for (const elem of iconElements) {
if (elem.closest("div.CowbellStorePanel_avatarsTab__1nnOY")) {
continue; // 商店页面
}
const playerId = findPlayerIdByAvatarElem(elem);
if (!playerId) {
console.error("ICONS: replaceIconsIn can't find playerId");
console.log(elem);
continue; // 找不到 playerId
}
if (!qqshowReplacementTargets.hasOwnProperty(playerId)) {
continue; // 没有配置图片地址
}
const newImgElement = document.createElement("img");
newImgElement.src = qqshowReplacementTargets[playerId];
newImgElement.style.width = "100%";
newImgElement.style.height = "auto";
elem.innerHTML = "";
elem.appendChild(newImgElement);
}
}
function findPlayerIdByAvatarElem(avatarElem) {
// Profile 窗口页
const profilePageDiv = avatarElem.closest("div.SharableProfile_modal__2OmCQ");
if (profilePageDiv) {
return profilePageDiv.querySelector(".CharacterName_name__1amXp")?.textContent.trim();
}
// 网页右上角
const headerDiv = avatarElem.closest("div.Header_header__1DxsV");
if (headerDiv) {
return headerDiv.querySelector(".CharacterName_name__1amXp")?.textContent.trim();
}
// 战斗页面
const combatDiv = avatarElem.closest("div.CombatUnit_combatUnit__1m3XT");
if (combatDiv) {
return combatDiv.querySelector(".CombatUnit_name__1SlO1")?.textContent.trim();
}
// 组队页面
const partyDiv = avatarElem.closest("div.Party_partySlot__1xuiq");
if (partyDiv) {
return partyDiv.querySelector(".CharacterName_name__1amXp")?.textContent.trim();
}
return null;
}
const qqshowObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (
node.tagName === "DIV" &&
!node.classList.contains("ProgressBar_innerBar__3Z_sf") &&
!node.classList.contains("CountdownOverlay_countdownOverlay__2QRmL") &&
!node.classList.contains("ChatMessage_chatMessage__2wev4") &&
!node.classList.contains("Header_loot__18Cbe") &&
!node.classList.contains("script_itemLevel") &&
!node.classList.contains("script_key") &&
!node.classList.contains("dps-info") &&
!node.classList.contains("MuiTooltip-popper")
) {
replaceIconsIn(node);
}
});
});
});
if(isQQshowServerAlive)qqshowObserver.observe(document, { attributes: false, childList: true, subtree: true });
// 显示提醒
// showToast()
// Source: **助手
// author: Trutn_Light Stella
const toastQueues = Array.from({ length: 5 }, () => []);
const maxVisibleToasts = Math.floor(window.innerHeight / 2 / 50);
let isToastVisible = Array(5).fill(false);
function displayNextToast(queueIndex) {
if (isToastVisible[queueIndex] || toastQueues[queueIndex].length === 0) return;
const { message, duration } = toastQueues[queueIndex].shift();
isToastVisible[queueIndex] = true;
const toast = createToastElement(message, queueIndex);
toast.style.opacity = '0';
requestAnimationFrame(() => {
toast.style.opacity = '1';
});
setTimeout(() => {
toast.style.opacity = '0';
setTimeout(() => {
document.body.removeChild(toast);
isToastVisible[queueIndex] = false;
displayNextToast(queueIndex);
}, 500);
}, duration);
}
function showToast(message, duration = 2000) {
const queueIndex = toastQueues.findIndex(queue => queue.length < maxVisibleToasts);
if (queueIndex === -1) return;
toastQueues[queueIndex].push({ message, duration });
displayNextToast(queueIndex);
}
function createToastElement(message, queueIndex) {
const toast = document.createElement('div');
toast.className = 'toast';
toast.style.position = 'fixed';
toast.style.bottom = `${20 + queueIndex * 60}px`;
toast.style.left = '50%';
toast.style.transform = 'translateX(-50%)';
toast.style.backgroundColor = '#333';
toast.style.color = '#fff';
toast.style.padding = '10px 20px';
toast.style.borderRadius = '5px';
toast.style.zIndex = '1000';
toast.style.textAlign = 'center';
toast.style.transition = 'opacity 0.5s';
toast.textContent = message;
document.body.appendChild(toast);
return toast;
}
//other
})();