@sjtdev/koishi-plugin-dota2tracker
Version:
koishi插件-追踪群友的DOTA2对局 | A Koishi plugin to track Dota 2 matches
792 lines (786 loc) • 267 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __glob = (map) => (path6) => {
var fn = map[path6];
if (fn) return fn();
throw new Error("Module not found in bundle: " + path6);
};
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name2 in all)
__defProp(target, name2, { get: all[name2], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/locales/en-US.constants.json
var require_en_US_constants = __commonJS({
"src/locales/en-US.constants.json"(exports2, module2) {
module2.exports = {
dota2tracker: {
usage: "DOTA2Bot plugin - provides the functionality to automatically track the latest matches of group members (requires group members to bind), as well as a series of query functions. \n[Localization/dota2tracker](../../locales/dota2tracker) allows customization of hero aliases and position nicknames, etc. \n**For more information, please visit the [plugin homepage](https://sjtdev.github.io/koishi-plugin-dota2tracker/) and [changelog](https://github.com/sjtdev/koishi-plugin-dota2tracker/blob/master/changelog.md).**",
usage_cron: "<p style='color: #FF9800;'> currently does not have<b> cron service </b>enabled, and can only provide query services. <br>If you need to enable active messaging services such as battle report tracking, please restart the plugin after the <b> cron service </b> is configured. </p>",
template: {
game_modes: {
NONE: "None",
ALL_PICK: "All Pick",
CAPTAINS_MODE: "Captains Mode",
RANDOM_DRAFT: "Random Draft",
SINGLE_DRAFT: "Single Draft",
ALL_RANDOM: "All Random",
INTRO: "Intro",
THE_DIRETIDE: "The Diretide",
REVERSE_CAPTAINS_MODE: "Reverse Captains Mode",
THE_GREEVILING: "The Greeviling",
TUTORIAL: "Tutorial",
MID_ONLY: "Mid Only",
LEAST_PLAYED: "Least Played",
NEW_PLAYER_POOL: "New Player Pool",
COMPENDIUM_MATCHMAKING: "Compendium Matchmaking",
CUSTOM: "Custom",
CAPTAINS_DRAFT: "Captains Draft",
BALANCED_DRAFT: "Balanced Draft",
ABILITY_DRAFT: "Ability Draft",
EVENT: "Event",
ALL_RANDOM_DEATH_MATCH: "All Random Death Match",
SOLO_MID: "Solo Mid",
ALL_PICK_RANKED: "All Pick",
TURBO: "Turbo",
MUTATION: "Mutation",
UNKNOWN: "Unknown"
},
lobby_types: {
INVALID: "Invalid",
UNRANKED: "Unranked",
PRACTICE: "Practice",
TOURNAMENT: "Tournament",
TUTORIAL: "Tutorial",
COOP_VS_BOTS: "Coop Vs Bots",
TEAM_MATCH: "Team Match",
SOLO_QUEUE: "Solo Queue",
RANKED: "Ranked",
SOLO_MID: "Solo Mid",
BATTLE_CUP: "Battle Cup",
EVENT: "Event",
NEW_PLAYER_POOL: "New Player Pool"
},
regions: {
"0": "Unknown",
"1": "US West",
"2": "US East",
"3": "Europe West",
"5": "SE Asia",
"6": "Dubai",
"7": "Australia",
"8": "Russia",
"9": "EU East",
"10": "South America",
"11": "South Africa",
"12": "China",
"13": "China",
"14": "Chile",
"15": "Peru",
"16": "India",
"17": "China",
"18": "China",
"19": "Japan",
"20": "China",
"25": "China",
"37": "Taiwan",
"38": "Argentina"
},
ranks: {
"0": "Unknown",
"1": "Herald",
"2": "Guardian",
"3": "Crusader",
"4": "Archon",
"5": "Legend",
"6": "Ancient",
"7": "Divine",
"8": "Immortal"
},
roles: {
"0": "Carry",
"1": "Support",
"2": "Nuker",
"3": "Disabler",
"4": "Jungler",
"5": "Durable",
"6": "Escape",
"7": "Pusher",
"8": "Initiator"
},
hero_names: {
"1": "Anti-Mage",
"2": "Axe",
"3": "Bane",
"4": "Bloodseeker",
"5": "Crystal Maiden",
"6": "Drow Ranger",
"7": "Earthshaker",
"8": "Juggernaut",
"9": "Mirana",
"10": "Morphling",
"11": "Shadow Fiend",
"12": "Phantom Lancer",
"13": "Puck",
"14": "Pudge",
"15": "Razor",
"16": "Sand King",
"17": "Storm Spirit",
"18": "Sven",
"19": "Tiny",
"20": "Vengeful Spirit",
"21": "Windranger",
"22": "Zeus",
"23": "Kunkka",
"25": "Lina",
"26": "Lion",
"27": "Shadow Shaman",
"28": "Slardar",
"29": "Tidehunter",
"30": "Witch Doctor",
"31": "Lich",
"32": "Riki",
"33": "Enigma",
"34": "Tinker",
"35": "Sniper",
"36": "Necrophos",
"37": "Warlock",
"38": "Beastmaster",
"39": "Queen of Pain",
"40": "Venomancer",
"41": "Faceless Void",
"42": "Wraith King",
"43": "Death Prophet",
"44": "Phantom Assassin",
"45": "Pugna",
"46": "Templar Assassin",
"47": "Viper",
"48": "Luna",
"49": "Dragon Knight",
"50": "Dazzle",
"51": "Clockwerk",
"52": "Leshrac",
"53": "Nature's Prophet",
"54": "Lifestealer",
"55": "Dark Seer",
"56": "Clinkz",
"57": "Omniknight",
"58": "Enchantress",
"59": "Huskar",
"60": "Night Stalker",
"61": "Broodmother",
"62": "Bounty Hunter",
"63": "Weaver",
"64": "Jakiro",
"65": "Batrider",
"66": "Chen",
"67": "Spectre",
"68": "Ancient Apparition",
"69": "Doom",
"70": "Ursa",
"71": "Spirit Breaker",
"72": "Gyrocopter",
"73": "Alchemist",
"74": "Invoker",
"75": "Silencer",
"76": "Outworld Devourer",
"77": "Lycan",
"78": "Brewmaster",
"79": "Shadow Demon",
"80": "Lone Druid",
"81": "Chaos Knight",
"82": "Meepo",
"83": "Treant Protector",
"84": "Ogre Magi",
"85": "Undying",
"86": "Rubick",
"87": "Disruptor",
"88": "Nyx Assassin",
"89": "Naga Siren",
"90": "Keeper of the Light",
"91": "Io",
"92": "Visage",
"93": "Slark",
"94": "Medusa",
"95": "Troll Warlord",
"96": "Centaur Warrunner",
"97": "Magnus",
"98": "Timbersaw",
"99": "Bristleback",
"100": "Tusk",
"101": "Skywrath Mage",
"102": "Abaddon",
"103": "Elder Titan",
"104": "Legion Commander",
"105": "Techies",
"106": "Ember Spirit",
"107": "Earth Spirit",
"108": "Underlord",
"109": "Terrorblade",
"110": "Phoenix",
"111": "Oracle",
"112": "Winter Wyvern",
"113": "Arc Warden",
"114": "Monkey King",
"119": "Dark Willow",
"120": "Pangolier",
"121": "Grimstroke",
"123": "Hoodwink",
"126": "Void Spirit",
"128": "Snapfire",
"129": "Mars",
"131": "Ring Master",
"135": "Dawnbreaker",
"136": "Marci",
"137": "Primal Beast",
"138": "Muerta",
"145": "Kez",
"155": "Largo"
},
behavior: {
"Unit Target": "Unit Target",
Channeled: "Channeled",
Hidden: "Hidden",
Passive: "Passive",
"No Target": "No Target",
Autocast: "Autocast",
"Instant Cast": "Instant Cast",
"Point Target": "Point Target",
"Attack Modifier": "Attack Modifier",
AOE: "AOE"
},
target_team: {
Enemy: "Enemy",
Both: "Both",
Friendly: "Friendly"
},
ability: "Ability: ",
affects: "Affects:",
damage_type: "Damage Type: ",
damage_type_Physical: "Physical",
damage_type_Magical: "Magical",
damage_type_Pure: "Pure",
dispellable: "Dispellable: ",
Yes: "Yes",
No: "No",
dispellable_Strong: "Strong Dispels Only",
bkbpierce: "Pierces Debuff Imminity: ",
innate: "Innate",
scepter: "Aghanim's Scepter",
shard: "Aghanim's Shard",
attack: "ATTACK",
defense: "DEFENSE",
mobility: "MOBILITY",
item_token: {
health: "Health",
mana: "Mana",
armor: "Armor",
damage: "Damage",
str: "Strength",
int: "Intelligence",
agi: "Agility",
all: "All Attributes",
primary_attribute: "Primary Attribute",
attack: "Attack Speed",
attack_pct: "Base Attack Speed Percentage",
hp_regen: "Health Regeneration",
lifesteal: "Lifesteal",
mana_regen: "Mana Regeneration",
mana_regen_aura: "Mana Regeneration Aura",
spell_amp: "Spell Damage",
debuff_amp: "Debuff Duration",
move_speed: "Movement Speed",
evasion: "Evasion",
spell_resist: "Magic Resistance",
spell_lifesteal: "Spell Lifesteal",
spell_lifesteal_hero_attacks: "Attacks on Heroes",
spell_lifesteal_hero_spells: "Abilities on Heroes",
spell_lifesteal_creep_attacks: "Attacks on Creeps",
spell_lifesteal_creep_spells: "Abilities on Creeps",
lifesteal_hero_attacks: "Attacks on Heroes",
lifesteal_hero_spells: "Abilities on Heroes",
lifesteal_creep_attacks: "Attacks on Creeps",
lifesteal_creep_spells: "Abilities on Creeps",
selected_attrib: "Selected Attribute",
attack_range: "Attack Range <font color='#7d7d7d'>(Ranged Only)</font>",
attack_range_melee: "Attack Range <font color='#7d7d7d'>(Melee Only)</font>",
attack_range_all: "Attack Range <font color='#7d7d7d'>(Melee & Ranged)</font>",
cast_range: "Cast Range",
status_resist: "Status Resistance",
projectile_speed: "Projectile Speed",
manacost_reduction: "Manacost Reduction",
cooldown_reduction: "Cooldown Reduction",
max_mana_percentage: "Max Mana Bonus",
slow_resistance: "Slow Resistance",
aoe_bonus: "AoE Bonus",
exclusive_movespeed: "Boot Movement Speed",
healing_amp: "Outgoing Heal Amplification"
},
recipe: "Recipe"
}
}
};
}
});
// src/locales/zh-CN.constants.json
var require_zh_CN_constants = __commonJS({
"src/locales/zh-CN.constants.json"(exports2, module2) {
module2.exports = {
dota2tracker: {
usage: "DOTA2Bot插件-提供自动追踪群友的最新对局的功能(需群友绑定),以及一系列查询功能。 \n[本地化/dota2tracker](../../locales/dota2tracker)可以自定义英雄别名和位置代称等文本内容 \n**更多信息请进入[插件主页](https://sjtdev.github.io/koishi-plugin-dota2tracker/)与[更新日志](https://github.com/sjtdev/koishi-plugin-dota2tracker/blob/master/changelog.md)查看。**",
usage_cron: "<p style='color: #FF9800;'>当前未启用<b> cron服务 </b>,仅能提供查询服务。<br>若需开启战报追踪等主动消息服务,请于配置完成 <b> cron服务 </b> 后重启本插件。</p>",
template: {
game_modes: {
NONE: "未知",
ALL_PICK: "全英雄选择",
CAPTAINS_MODE: "队长模式",
RANDOM_DRAFT: "随机征召",
SINGLE_DRAFT: "单一征召",
ALL_RANDOM: "全英雄随机",
INTRO: "",
THE_DIRETIDE: "",
REVERSE_CAPTAINS_MODE: "",
THE_GREEVILING: "",
TUTORIAL: "教程模式",
MID_ONLY: "",
LEAST_PLAYED: "",
NEW_PLAYER_POOL: "",
COMPENDIUM_MATCHMAKING: "",
CUSTOM: "",
CAPTAINS_DRAFT: "",
BALANCED_DRAFT: "",
ABILITY_DRAFT: "",
EVENT: "",
ALL_RANDOM_DEATH_MATCH: "",
SOLO_MID: "",
ALL_PICK_RANKED: "全英雄选择",
TURBO: "加速模式",
MUTATION: "",
UNKNOWN: "未知"
},
lobby_types: {
INVALID: "",
UNRANKED: "非天梯",
PRACTICE: "",
TOURNAMENT: "",
TUTORIAL: "",
COOP_VS_BOTS: "",
TEAM_MATCH: "",
SOLO_QUEUE: "",
RANKED: "天梯比赛",
SOLO_MID: "",
BATTLE_CUP: "",
EVENT: "",
NEW_PLAYER_POOL: ""
},
regions: {
"0": "未知",
"1": "US WEST",
"2": "US EAST",
"3": "EUROPE",
"5": "新加坡",
"6": "DUBAI",
"7": "AUSTRALIA",
"8": "STOCKHOLM",
"9": "AUSTRIA",
"10": "BRAZIL",
"11": "SOUTHAFRICA",
"12": "电信(上海)",
"13": "联通(一)",
"14": "CHILE",
"15": "PERU",
"16": "INDIA",
"17": "电信(广东)",
"18": "电信(浙江)",
"19": "日本",
"20": "电信(华中)",
"25": "联通(二)",
"37": "TAIWAN",
"38": "ARGENTINA"
},
ranks: {
"0": "未知",
"1": "先锋",
"2": "卫士",
"3": "中军",
"4": "统帅",
"5": "传奇",
"6": "万古流芳",
"7": "超凡入圣",
"8": "冠绝一世"
},
roles: {
"0": "核心",
"1": "辅助",
"2": "爆发",
"3": "控制",
"4": "打野",
"5": "耐久",
"6": "逃生",
"7": "推进",
"8": "先手"
},
hero_names: {
"1": "敌法师",
"2": "斧王",
"3": "祸乱之源",
"4": "血魔",
"5": "水晶室女",
"6": "卓尔游侠",
"7": "撼地者",
"8": "主宰",
"9": "米拉娜",
"10": "变体精灵",
"11": "影魔",
"12": "幻影长矛手",
"13": "帕克",
"14": "帕吉",
"15": "雷泽",
"16": "沙王",
"17": "风暴之灵",
"18": "斯温",
"19": "小小",
"20": "复仇之魂",
"21": "风行者",
"22": "宙斯",
"23": "昆卡",
"25": "莉娜",
"26": "莱恩",
"27": "暗影萨满",
"28": "斯拉达",
"29": "潮汐猎人",
"30": "巫医",
"31": "巫妖",
"32": "力丸",
"33": "谜团",
"34": "修补匠",
"35": "狙击手",
"36": "瘟疫法师",
"37": "术士",
"38": "兽王",
"39": "痛苦女王",
"40": "剧毒术士",
"41": "虚空假面",
"42": "冥魂大帝",
"43": "死亡先知",
"44": "幻影刺客",
"45": "帕格纳",
"46": "圣堂刺客",
"47": "冥界亚龙",
"48": "露娜",
"49": "龙骑士",
"50": "戴泽",
"51": "发条技师",
"52": "拉席克",
"53": "先知",
"54": "噬魂鬼",
"55": "黑暗贤者",
"56": "克林克兹",
"57": "全能骑士",
"58": "魅惑魔女",
"59": "哈斯卡",
"60": "暗夜魔王",
"61": "育母蜘蛛",
"62": "赏金猎人",
"63": "编织者",
"64": "杰奇洛",
"65": "蝙蝠骑士",
"66": "陈",
"67": "幽鬼",
"68": "远古冰魄",
"69": "末日使者",
"70": "熊战士",
"71": "裂魂人",
"72": "矮人直升机",
"73": "炼金术士",
"74": "祈求者",
"75": "沉默术士",
"76": "殁境神蚀者",
"77": "狼人",
"78": "酒仙",
"79": "暗影恶魔",
"80": "德鲁伊",
"81": "混沌骑士",
"82": "米波",
"83": "树精卫士",
"84": "食人魔魔法师",
"85": "不朽尸王",
"86": "拉比克",
"87": "干扰者",
"88": "司夜刺客",
"89": "娜迦海妖",
"90": "光之守卫",
"91": "艾欧",
"92": "维萨吉",
"93": "斯拉克",
"94": "美杜莎",
"95": "巨魔战将",
"96": "半人马战行者",
"97": "马格纳斯",
"98": "伐木机",
"99": "钢背兽",
"100": "巨牙海民",
"101": "天怒法师",
"102": "亚巴顿",
"103": "上古巨神",
"104": "军团指挥官",
"105": "工程师",
"106": "灰烬之灵",
"107": "大地之灵",
"108": "孽主",
"109": "恐怖利刃",
"110": "凤凰",
"111": "神谕者",
"112": "寒冬飞龙",
"113": "天穹守望者",
"114": "齐天大圣",
"119": "邪影芳灵",
"120": "石鳞剑士",
"121": "天涯墨客",
"123": "森海飞霞",
"126": "虚无之灵",
"128": "电炎绝手",
"129": "玛尔斯",
"131": "百戏大王",
"135": "破晓辰星",
"136": "玛西",
"137": "獸",
"138": "琼英碧灵",
"145": "凯",
"155": "朗戈"
},
behavior: {
"Unit Target": "单位目标",
Channeled: "持续施法",
Hidden: "默认隐藏",
Passive: "被动",
"No Target": "无目标",
Autocast: "自动施法",
"Instant Cast": "即时施法",
"Point Target": "点目标",
"Attack Modifier": "攻击特效",
AOE: "范围生效"
},
target_team: {
Enemy: "敌方单位",
Both: "单位",
Friendly: "友方单位"
},
ability: "技能:",
affects: "影响:",
damage_type: "伤害类型:",
damage_type_Physical: "物理",
damage_type_Magical: "魔法",
damage_type_Pure: "纯粹",
dispellable: "能否驱散:",
Yes: "是",
No: "否",
dispellable_Strong: "仅强驱散",
bkbpierce: "无视减益免疫:",
innate: "先天技能",
scepter: "阿哈利姆神杖",
shard: "阿哈利姆魔晶",
attack: "进攻",
defense: "防守",
mobility: "机动",
item_token: {
health: "生命值",
mana: "魔法值",
armor: "护甲",
damage: "攻击力",
str: "力量",
int: "智力",
agi: "敏捷",
all: "全属性",
primary_attribute: "主属性",
attack: "攻击速度",
attack_pct: "基础攻击速度",
hp_regen: "生命恢复",
lifesteal: "吸血",
mana_regen: "魔法恢复",
mana_regen_aura: "魔法恢复光环",
spell_amp: "技能伤害",
debuff_amp: "负面状态持续时间",
move_speed: "移动速度",
evasion: "闪避",
spell_resist: "魔法抗性",
spell_lifesteal: "技能吸血",
spell_lifesteal_hero_attacks: "对英雄的攻击",
spell_lifesteal_hero_spells: "对英雄的技能",
spell_lifesteal_creep_attacks: "对非英雄的攻击",
spell_lifesteal_creep_spells: "对非英雄的技能",
lifesteal_hero_attacks: "对英雄的攻击",
lifesteal_hero_spells: "对英雄的技能",
lifesteal_creep_attacks: "对非英雄的攻击",
lifesteal_creep_spells: "对非英雄的技能",
selected_attrib: "所选属性",
attack_range: "攻击距离<font color='#7d7d7d'>(仅对远程有效)</font>",
attack_range_melee: "攻击距离<font color='#7d7d7d'>(仅对近战有效)</font>",
attack_range_all: "攻击距离<font color='#7d7d7d'>(近战和远程)</font>",
cast_range: "施法距离",
status_resist: "状态抗性",
projectile_speed: "弹道速度",
manacost_reduction: "魔法消耗降低",
cooldown_reduction: "冷却时间减少",
max_mana_percentage: "额外最大魔法值",
slow_resistance: "减速抗性",
aoe_bonus: "作用范围加成",
exclusive_movespeed: "移动速度加成",
healing_amp: "对外治疗增强"
},
recipe: "图纸"
},
items_alias: {
"3800": ["圣者遗物"],
跳刀: ["闪烁匕首"],
力量跳刀: ["盛势闪光"],
敏捷跳刀: ["迅疾闪光"],
智力跳刀: ["秘奥闪光"],
补刀斧: ["压制之刃"],
仙草: ["仙灵之火"],
仙火: ["仙灵之火"],
魂泪: ["凝魂之露"],
鞋垫: ["风灵之纹"],
银月: ["银月之晶"],
树枝: ["铁树枝干"],
草鞋: ["速度之靴"],
魔棒: ["魔棒", "魔杖"],
大魔棒: ["魔杖"],
绿杖: ["幽魂权杖"],
小蓝: ["净化药水"],
蓝瓶: ["净化药水"],
大药: ["治疗药膏"],
粉: ["显影之尘"],
瓶子: ["魔瓶"],
假眼: ["侦察守卫"],
真眼: ["岗哨守卫"],
吃树: ["树之祭祀"],
TP: ["回城卷轴"],
飞鞋: ["远行鞋"],
相位: ["相位鞋"],
鹰角弓: ["鹰歌弓"],
大斧: ["掠夺者之斧"],
回5: ["治疗指环"],
假腿: ["动力鞋"],
点金: ["迈达斯之手"],
系带: ["怨灵系带"],
挂件: ["空灵挂件"],
骨灰: ["影之灵龛", "魂之灵瓮"],
羊刀: ["邪恶镰刀"],
紫苑: ["紫怨", "血棘"],
大紫怨: ["血棘"],
大紫苑: ["血棘"],
紫怨: ["血棘"],
血辣: ["血棘"],
连击刀: ["回音战刃"],
吹风: ["Eul的神圣法杖", "风之杖"],
大吹风: ["风之杖"],
以太: ["以太透镜"],
推推: ["原力法杖", "飓风长戟"],
推推棒: ["原力法杖", "飓风长戟"],
大推推: ["飓风长戟"],
大根: ["达贡之神力"],
A杖: ["阿哈利姆神杖"],
刷新: ["刷新球"],
强袭: ["强袭胸甲"],
龙心: ["恐鳌之心"],
BKB: ["黑皇杖"],
不朽盾: ["不朽之守护"],
冰甲: ["希瓦的守护"],
莲花: ["清莲宝珠"],
盘子: ["永恒之盘"],
大骨灰: ["魂之灵瓮"],
法式泳衣: ["永世法衣"],
MKB: ["金箍棒"],
大炮: ["代达罗斯之殇"],
晕锤: ["碎颅锤", "深渊之刃"],
分身: ["幻影斧"],
隐刀: ["影刃", "白银之锋"],
大隐刀: ["白银之锋"],
大电锤: ["雷神之锤"],
电锤: ["雷神之锤", "漩涡"],
冰眼: ["斯嘉蒂之眼"],
大支配: ["统御头盔"],
支配: ["统御头盔"],
雷托斯: ["缚灵索"],
暗灭: ["黯灭"],
疯脸: ["疯狂面具"],
散失: ["净魂之刃", "散魂剑"],
大散失: ["散魂剑"],
虚灵刀: ["虚灵之刃"],
魂戒: ["灵魂之戒"],
秘法鞋: ["奥术鞋"],
毒球: ["淬毒之珠"],
减甲球: ["枯萎之珠"],
大毒球: ["腐蚀之球"],
冰球: ["冰霜之珠"],
骗钱刀: ["猎鹰战刃"],
法克: ["法师克星"],
战鼓: ["韧鼓"],
大绿鞋: ["宽容之靴"],
勋章: ["勇气勋章", "炎阳纹章"],
大勋章: ["炎阳纹章"],
雾: ["诡计之雾"],
大鞋: ["卫士胫甲"],
阿托斯: ["阿托斯之棍"],
打野爪: ["寒铁钢爪"],
大晕锤: ["深渊之刃"],
天堂: ["天堂之戟"],
天鹰戒: ["天鹰之戒"],
绿鞋: ["静谧之鞋"],
微光: ["微光披风"],
工资球: ["贤者石"],
推推鞋: ["原力鞋"],
大暗灭: ["寂灭"],
铲子: ["可靠铁铲"]
}
}
};
}
});
// src/locales/en-US.command.yml
var require_en_US_command = __commonJS({
"src/locales/en-US.command.yml"(exports2, module2) {
module2.exports = { commands: { dota2tracker: { description: "A series of commands for Dota 2 Tracker. Use dota2tracker -h to see all available commands, or use dota2tracker.help to see a detailed description of all commands.", subscribe: { description: "Subscribes the current channel to Dota 2 match tracking.", usage: "After subscribing, players need to bind their Steam ID in this channel. The bot will then track new matches of bound players and post image-based reports upon completion of parsing by Stratz.", examples: "subscribe", messages: { subscribe_success: "Subscription successful.", subscribed: "This Channel has been subscribed, no need to subscribe again." } }, unsubscribe: { description: "Unsubscribes the current channel from match tracking.", usage: "Unsubscribes the current channel from match tracking.", examples: "unsubscribe", messages: { unsubscribe_success: "Unsubscription successful.", not_subscribed: "This Channel has not been subscribed yet, so there is no need to unsubscribe." } }, bind: { description: "Binds your SteamID to your account in the current channel.", usage: 'Bind your SteamID to your account. If the channel is subscribed, your new match data will be posted automatically. Nicknames containing spaces must be enclosed in double quotes ("").', examples: 'bind 123456789\nbind 123456789 John\nbind 123456789 "John Doe"', messages: { steam_id_invalid: "Invalid SteamID.", bind_success: "Binding successful,\nID: {userId}\nNickname: {nickName}\nSteamID: {steamId}", bind_failed: "Binding failed, {0}", reason_without_match: "Invalid SteamID or no matches found.", reason_fetch_failed: "Poor network conditions or other reasons prevented the verification of the SteamID. Please try again later.", already_binded: "You are already bound, no need to bind again.\nHere is your personal information:\nID: {userId}\nNickname: {nickName}\nSteamID: {steamId}", nick_name_too_long: "Nickname is too long, please limit it to 20 characters or less. (It can also be left blank)", is_anonymous: 'Please note: Your Steam player data is not public, and you will not be able to use the main functions of the BOT, such as "battle report tracking," "query-recent-match commands," etc.\nIf you need to make data public, please set it to public in the DOTA2 game settings.' } }, unbind: { description: "Unbinds your personal information in the current channel.", usage: "Unbind your personal information in the current channel.", examples: "unbind", messages: { unbind_success: "Unbinding successful.", not_binded: "Not bound, no need to unbind." } }, rename: { description: "Changes the nickname set during binding.", usage: 'Change the nickname set during binding. Nicknames containing spaces must be enclosed in double quotes ("").', examples: 'rename John\nrename "John Doe"', messages: { rename_success: "Rename successful, now you are called {nick_name}.", empty_input: "Please enter your nickname.", not_binded: "Please bind first, you can set a nickname during binding.", nick_name_too_long: "Nickname is too long, please limit it to 20 characters.", nick_name_same: "The input content is the same as the original nickname and does not need to be renamed." } }, "query-members": { description: "Queries the players bound in this channel and generates an info image.", usage: "Queries the players bound in this channel and generates an informational image.", examples: "query-members", messages: { title: "Guild DOTA 2 Roster (Total: {count})", table_headers: { nickname: "Nickname", winrate: "Win Rate (L10)", last_match: "Last Match" }, no_members: "No players bound in this group.", query_failed: "Failed to query group members." } }, "query-match": { description: "Query the match data of the specified match ID and generate a picture.", usage: "Query the match data of the specified match ID and generate a picture.", options: { parse: "Whether to wait for match data parsing" }, examples: "query-match 1234567890\nquery-match 1234567890 -p\nquery-match 1234567890 --parse", messages: { empty_input: "Please enter the match ID.", match_id_invalid: "Invalid match ID.", querying_match: "Searching for match details, please wait...", query_failed: "Failed to get match data.", waiting_for_parse: "Match data has not been parsed yet, a parse request has been sent to the server. The battle report will be sent once parsing is complete or times out." } }, "query-recent-match": { description: "Query the most recent match data and generate a picture.", options: { parse: "Whether to wait for match data parsing" }, usage: "Query the most recent match data of the specified player and generate a picture.\nThe parameter can be the player's SteamID or the nickname of a player bound in this group. If no parameter is provided, it will try to query the SteamID of the command caller.", examples: "query-recent-match\nquery-recent-match 123456789\nquery-recent-match John\nquery-recent-match 123456789 -p\nquery-recent-match John --parse", messages: { querying_match: "Searching for match details, please wait...", query_failed: "Failed to get the player's recent match.", is_anonymous: "Your player data is not public, and recent match data cannot be obtained.\nIf you need to make data public, please set it to public in the DOTA2 game settings." } }, "query-player": { description: "Query the player's personal information, optionally specify a hero.", options: { hero: "Query the player's usage of the specified hero (same as querying a hero, can use nickname or ID)" }, usage: "Query the personal information of the specified player and generate a picture, optionally specify a hero.\nThe parameter can be the player's SteamID or the nickname of a player bound in this group. If no parameter is provided, it will try to query the SteamID of the command caller.", examples: "query-player\nquery-player 123456789\nquery-player John\nquery-player John --hero Anti-Mage\nquery-player John -o Anti-Mage", messages: { querying_player: "Retrieving player data, please wait...", query_failed: "Failed to get player information." } }, "query-hero": { description: "Query hero skills/stats information.", options: { random: "Randomly select a hero." }, usage: "Query the hero's skill descriptions and various stats, generate a picture.\nThe parameter can be the hero's ID, name, or common nickname.", examples: "query-hero 15\nquery-hero Razor\nquery-hero -r", messages: { not_found: "Hero not found, please confirm and re-enter.", querying_hero: "Retrieving hero data, please wait...", query_failed: "Failed to get hero data.", empty_input: "Please enter a parameter." } }, "query-item": { description: "Query item information", usage: "Query item descriptions and attributes, then generate and publish an image report.\nParameters can be item name (supports fuzzy search), item alias, or item ID.\nYou can set the maximum number of items to send per query on the configuration page, as well as whether to send the item list when the limit is exceeded or parameters are not entered.", examples: "query-item Vanguard", messages: { query_list_failed: "Failed to retrieve item list data", query_item_failed: "Failed to retrieve data for item '{0}'", querying_item: "Querying item data, please wait...", cache_building: "Initializing or rebuilding item cache for the current version, please wait...", empty_input: "No keywords provided. \n{#if show}Displaying full item list per current configuration\n{:else}No content available\n{/if}", not_found: "No items found matching the keywords, please verify and retry", too_many_items: "Found {count} items, exceeding maximum display limit ({max} items)\n{#if show}(Displaying item list){/if}", finded_items: "Matching items: \n{#each items as item}\n{item.name_loc}{#if item !== items[items.length - 1]}, {/if}\n{/each}" } }, "hero-of-the-day": { description: "Get hero recommendations for the day.", usage: "Fetches recent and lifetime match history to recommend heroes based on parameters like wins, performance score, and hot streaks.\nThe parameter can be a player's SteamID or the nickname of a player bound in this group. If no parameter is provided, it will try to look up the command caller's SteamID.", options: { days: "-d <number> The range of recent days to consider, default is 30." }, examples: 'hero-of-the-day\nhero-of-the-day -d 60\nhero-of-the-day 1234567890\nhero-of-the-day "John Doe"', messages: { title_recommendation: "Today's Recommendation:", recommendation_intro: "The recommended heroes for you today are:", recommendation_heroes: "{#each heroes as hero}{hero}{#if hero !== heroes[heroes.length - 1]}, {/if}{/each}", recommendation_type_lifetime_only: "Your recent match history is empty. This recommendation is based on your lifetime statistics.", recommendation_type_no_record: "Recommendations cannot be generated due to a lack of recent and lifetime match data.", recommendation_type_anonymous: "Recommendations cannot be generated because your profile data is private.", details: { pool_description: "The recommendation is generated by scoring your recent and lifetime hero performance, sorting by total score, and then randomly selecting from the top 10 heroes weighted by their scores.", table_intro: "Below is the detailed score breakdown for the top 10 heroes.", table_headers: { hero: "Hero", recent_wins: "Recent Wins Score", lifetime_wins: "Lifetime Wins<br>(Logarithmic)", imp_bonus: "IMP Bonus", is_hot_streak: "Hot Streak", total_score: "Total Score" }, scoring_formula: "Current Scoring Formula: [Recent Wins x 1] + [log(Lifetime Wins + 1) x 5] + [Recent IMP x 0.1]", hot_streak_desc: "If a hero was played in the last 3 days, it's considered a 'Hot Streak' hero, receiving a 20% bonus to its total score." }, title_meta: "Meta Trends:", meta_intro: "Top 3 advantage heroes for each position with a <b>pick rate ≥2%</b> within ±1 of your rank bracket ({tiers}) over the last week, sorted by win rate:", meta_table_header: "Hero (Pick% Win%)", meta_position: "Pos {pos}:", querying: "Retrieving player stats and hero win rates, please wait...", query_failed: "Command failed." } }, common: { messages: { user_not_binded_in_channel: "By default, it tries to find your information from the bound SteamID players, but it seems you are not bound.\nPlease bind your SteamID in this group. (You can enter [bind -h] for help)\nOr follow the command with the SteamID or nickname of the player you want to query.", user_not_in_group: "Command failed.\nCurrently not in a group chat, you must provide the specified player's SteamID.", invalid_input_include_steam_id: "Invalid SteamID and the player was not found in this group by the given input." } }, help: { description: "Get detailed information for all commands and the link to the online documentation.", usage: "Get detailed information for all commands and the link to the online documentation.", examples: "help", messages: { header: "Below is the full list of plugin commands.\n※Note: <arg> is a required argument, and [arg] is an optional argument. Please see the 'Examples' column for specific usage.", footer: "For more information on plugin configuration, template showcases, and other details, please visit the online documentation:\nhttps://sjtdev.github.io/koishi-plugin-dota2tracker/en-US/", table_headers: { command: "Command", alias: "Alias", arguments: "Arguments", description: "Description", options: "Options", examples: "Examples" } } } } } };
}
});
// src/locales/en-US.schema.yml
var require_en_US_schema = __commonJS({
"src/locales/en-US.schema.yml"(exports2, module2) {
module2.exports = { _config: { base: { $desc: "Basic Settings", STRATZ_API_TOKEN: "Required. API TOKEN from stratz.com, available at https://stratz.com/api.", dataParsingTimeoutMinutes: "Time to wait for match data parsing (in minutes). If the data parsing time exceeds the waiting time, the report will be generated directly without waiting for the parsing to complete.", proxyAddress: "Proxy address. Leave blank if not using a proxy. \n※Cannot use the global proxy address configured by the `proxy-agent` plugin. This option must be set if you want to use a proxy.", suppressStratzNetworkErrors: "**Please use the `suppressApiNetworkErrors` option below, which applies to both Stratz and OpenDota. \nThis option is still effective. If either this or `suppressApiNetworkErrors` is enabled, Stratz/OpenDota logs will be downgraded to debug output. \nThis option will be removed in a future version.**", suppressApiNetworkErrors: "When enabled, Stratz/OpenDota network error logs will be output at the debug level. \n(e.g., timeouts, network connection issues, but excludes 403 Forbidden) \nKoishi does not display debug-level logs by default. To enable debug log display, please see [📖 Configs#suppressapinetworkerrors](https://sjtdev.github.io/koishi-plugin-dota2tracker/en-US/configs.html#suppressapinetworkerrors-boolean)", enableOpenDotaFallback: "Enable OpenDota as a fallback data source for match tracking and query-match features.", OPENDOTA_API_KEY: "Your paid subscription API key for OpenDota. \nSee https://www.opendota.com/api-keys for details. \nFree users should leave this blank.", OpenDotaIPStack: "If you experience frequent failures when accessing the OpenDota API, it might be caused by a faulty IPv6 environment. \nSetting this option will force the use of IPv4 when accessing the OpenDota API to try and resolve the issue." }, message: { $desc: "Message Settings", useHeroNicknames: "When disabled, only the official hero names will be used.", urlInMessageType: { $desc: "Include links in messages, <br/>please select the message type:", $inner: ["Include stratz match page link in match query and report messages", "Include stratz player page link in player information query messages", "Include Dota Encyclopedia hero page link in hero data query messages"] }, rankBroadSwitch: "Rank change broadcast", rankBroadStar: "Star change broadcast", rankBroadLeader: "Leaderboard rank change broadcast", rankBroadFun: "Fun broadcast template", maxSendItemCount: "Maximum number of item images to send<br/>When exceeded, the following option determines whether to send the item list", showItemListAtTooMuchItems: "Send item list when exceeding max count<br/>Controls whether to send the item list image when search results exceed maxSendItemCount", customItemAlias: { $desc: "Custom item aliases<br/>\nAdd additional aliases when built-in list is insufficient. \nFor widely-used missing aliases, please submit issues/pull requests to the source repository.<br/>\n(Example **Keyword**: Blink Dagger,**Alias**: Blink)", keyword: "Keyword", alias: "Alias" }, autoRecallTips: 'Automatically recall tip messages after the command finishes, e.g., "Searching for match details, please wait..."' }, report: { $desc: "Summary Settings", dailyReportSwitch: "Daily Report Function", dailyReportHours: "Daily report time in hours", dailyReportShowCombi: "*Show combinations in daily report*", weeklyReportSwitch: "Weekly Report Function", weeklyReportDayHours: "Weekly report published on (day) at (hour)", weeklyReportShowCombi: "Show combinations in weekly report" }, template: { $desc: "Template Settings", template_match: "Template used for generating match information images. See [📖 Template Info#Match Info Template](https://sjtdev.github.io/koishi-plugin-dota2tracker/en-US/template-match.html) for display effects.", template_player: "Template used for generating player information images. (Currently only one template available)", template_hero: "Template used for generating hero information images. (Currently only one template available)", playerRankEstimate: "Estimate rank for unranked players in the player template <br>Estimated ranks will be displayed as gray images", templateFonts: '**>Deprecated!<** \n**If you need to configure fonts, please use the `fonts.*` configuration option below instead!** \nFont names used in the template. Requires font files to be installed on the device running Koishi. \nMultiple font names can be added, and it will fallback from top to bottom to the first available font; if no fonts are available, the system default font will be used. \nIf a font name contains spaces or special characters, quotes must be added around the name (it is recommended to always use quotes here); \nIf using a generic font family name, you must **NOT use quotes**, e.g.:\n```\n"Microsoft YaHei"\nsans-serif\n```\nFor more information on font-family, please refer to [📖 MDN: font-family](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family)', fontPath: "Font directory path", fonts: { description: "**Interim solution. A more comprehensive and flexible font configuration scheme will be implemented in the console in the future.** \nFont configuration used in the template. \nIt will automatically scan font files in the `fontPath` directory to generate the selectable font list below. \nYou can separately configure fallback lists for sans-serif (sans), serif (serif), and monospace (mono) font families. \nThe main font type used in the templates is **sans-serif**, while some text in certain templates uses **serif** and **monospace** fonts. \nFor more information on font configuration, please refer to [📖 Template Info#Template Fonts](https://sjtdev.github.io/koishi-plugin-dota2tracker/en-US/template-fonts.html)", sans: { $desc: "Sans-serif fonts (sans-serif)" }, serif: { $desc: "Serif fonts (serif)" }, mono: { $desc: "Monospace fonts (monospace)" } } } } };
}
});
// src/locales/en-US.template.yml
var require_en_US_template = __commonJS({
"src/locales/en-US.template.yml"(exports2, module2) {
module2.exports = { dota2tracker: { template: { radiant: "Radiant", dire: "Dire", won: "Won", lost: "Lost", match_id_: "Match ID: {0}", game_mode_: "Mode: {0}", start_time_: "Start Time: {0}", end_time_: "End Time: {0}", pick_order: "#{0}", random: "R", hero_damage_: "Damage: {0}", building_damage_: "Building: {0}", damage_received_: "Received: {0}", lasthit_: "LastHit: {0}", deny_: "Deny: {0}", "lh/dn_": "LH/DN: {0}", GPM: "GPM", XPM: "XPM", heal_: "Heal: {0}", crowd_control_duration_: "CCD: {0}", "GPM/XPM_": "GPM/XPM: {0}", lane: "Lane", lane_: "Lane: ", lane_advantage: "Lane +", lane_disadvantage: "Lane -", lane_jungle: "Jungle", lane_stomp: "Lane+++", lane_stomped: "Lane---", lane_tie: "Lane ==", analysis_successful: "Analysis successful", analysis_incomplete: "Analysis incomplete", analysis_by_opendota: "Analysis by OpenDota", kill: "Kill", kill_contribution_: "KC: {0}", position: "Position", position_: "Position: ", position_1: "Carry", position_2: "Mid", position_3: "OffLane", position_4: "Softsup", position_5: "Hardsup", dire_won: "Dire Won", radiant_won: "Radiant Won", total_damage: "Damage", total_experience: "Exp.", total_gold: "Gold", region_: "Region: {0}", duration_: "Duration: {0}", position_undefined: "?", top10_: "Top 10 Heroes by Matches: ", match_count_: "Matches: ", last25matches_: "Last 25 Matches: ", winrate_: "Winrate: ", imp_: "IMP: ", lane_advantage_rate_: "Lane Advantage Rate: ", hero: "Hero", all_matches_: "All Matches: ", match_count: "Matches", winrate: "Winrate", imp: "IMP", win_count: "Wins", lose_count: "Losses", recently_heroes: "Heroes used more than once recently: ", recently_positions: "Performance in the last 25 matches across all positions: ", winning_streak: "Winning Streak", losing_streak: "Losing Streak", id: "ID", mode: "Mode", kda_kc: "KDA(KC)", time: "Time", duration: "Duration", rank: "Rank", un_parsed: "(Unparsed)", combined_win_loss_summary: "Combined Win/Loss Summary: ", yesterdays_summary: "Yesterday's Summary", last_weeks_summary: "Last Week's Summary", report_won: "W", report_lost: "L", report_winrate: "WR", anonymous_player_1: "This profile is private.", anonymous_player_2: "Background is for display purposes only. It is not {player}’s data.", rank_fun_down_message: "AVATAR_PLACEHOLDER<br/>Sad", rank_fun_up_message: "Hip hip hooray! Our awesome member AVATAR_PLACEHOLDER{name} has leveled up from PREV_PLACEHOLDER to CURR_PLACEHOLDER!", titles: { MVP: "MVP-#FFA500", Soul: "Soul-#66CCFF", Rich: "Rich-#FFD700", Wise: "Wise-#8888FF", Controller: "Controller-#FF00FF", Nuker: "Nuker-#CC0088", Breaker: "Breaker-#DD0000", Ghost: "Ghost-#CCCCCC", Utility: "Utility-#20B2AA", Assister: "Assister-#006400", Demolisher: "Demolisher-#FEDCBA", Healer: "Healer-#00FF00", Tank: "Tank-#84A1C7", Idle: "Idle-#DDDDDD" }, situation: "Situation", networth: "Net Worth", experience: "Experience", OUTCOME_MAP: { RADIANT_VICTORY: "RADIANT VICTORY", RADIANT_STOMP: "RADIANT STOMP", DIRE_VICTORY: "DIRE VICTORY", DIRE_STOMP: "DIRE STOMP", TIE: "TIE" }, lane_top: "Top", lane_mid: "Mid", lane_bottom: "Bottom", empty_extra_info: "No extra info", opendota: { networth_unavailable: "Net Worth Chart Unavailable", networth_unavailable_reason: "Data source OpenDota does not provide per-minute net worth data.", lane_outcome_tip: "(Based on gold earned, not net worth; ref only.)", gold_t: "Gold Earned" }, report: { daily: { plugin_name: "Koishi Dota 2 Plugin", title: "Daily Group Recap", meta: { date_format: "cccc, LLLL d, yyyy", summary: "Performance summary for {0}.", footer_format: "ID: #{0} • Server: {1}" }, stats: { matches: "Matches", win_rate: "Win Rate", kills: "Total Kills", duration: "Duration", avg_time: "Avg", matches_subtext: "{0} W - {1} L", vs_yesterday: "vs Yesterday", kills_avg: "Avg {0}" }, spotlight: { mvp_title: "The King", lvp_title: "The Suspect", score_label: "MVP Score" }, squad: { title: "Performance", subtitle: "Ranked by KDA (desc)", header: { rank: "Rank", player_info: "Player Info", hero_pool: "Hero Pool (Sorted by Wins)", kda: "KDA Ratio", impact: "Impact" }, impact: { dmg: "Dmg", gold: "Gold" } }, footer: { generated_by: "Generated by Koishi Bot" } } } } } };
}
});
// src/locales/en-US.yml
var require_en_US = __commonJS({
"src/locales/en-US.yml"(exports2, module2) {
module2.exports = { dota2tracker: { heroes_nicknames: { "0": 'Please strictly follow the format of "", "" when filling out, if the format is incorrect, only the default name of the hero will be used. The default name of the hero may be omitted.', "1": '"Anti-Mage"', "2": '"Axe"', "3": '"Bane"', "4": '"Bloodseeker"', "5": '"Crystal Maiden"', "6": '"Drow Ranger"', "7": '"Earthshaker"', "8": '"Juggernaut"', "9": '"Mirana"', "10": '"Morphling"', "11": '"Shadow Fiend"', "12": '"Phantom Lancer"', "13": '"Puck"', "14": '"Pudge"', "15": '"Razor"', "16": '"Sand King"', "17": '"Storm Spirit"', "18": '"Sven"', "19": '"Tiny"', "20": '"Vengeful Spirit"', "21": '"Windranger"', "22": '"Zeus"', "23": '"Kunkka"', "25": '"Lina"', "26": '"Lion"', "27": '"Shadow Shaman"', "28": '"Slardar"', "29": '"Tidehunter"', "30": '"Witch Doctor"', "31": '"Lich"', "32": '"Riki"', "33": '"Enigma"', "34": '"Tinker"', "35": '"Sniper"', "36": '"Necrophos"', "37": '"Warlock"', "38": '"Beastmaster"', "39": '"Queen of Pain"', "40": '"Venomancer"', "41": '"Faceless Void"', "42": '"Wraith King"', "43": '"Death Prophet"', "44": '"Phantom Assassin"', "45": '"Pugna"', "46": '"Templar Assassin"', "47": '"Viper"', "48": '"Luna"', "49": '"Dragon Knight"', "50": '"Dazzle"', "51": '"Clockwerk"', "52": '"Leshrac"', "53": `"Nature's Prophet"`, "54": '"Lifestealer"', "55": '"Dark Seer"', "56": '"Clinkz"', "57": '"Omniknight"', "58": '"Enchantress"', "59": '"Huskar"', "60": '"Night Stalker"', "61": '"Broodmother"', "62": '"Bounty Hunter"', "63": '"Weaver"', "64": '"Jakiro"', "65": '"Batrider"', "66": '"Chen"', "67": '"Spectre"', "68": '"Ancient Apparition"', "69": '"Doom"', "70": '"Ursa"', "71": '"Spirit Breaker"', "72": '"Gyrocopter"', "73": '"Alchemist"', "74": '"Invoker"', "75": '"Silencer"', "76": '"Outworld Devourer"', "77": '"Lycan"', "78": '"Brewmaster"', "79": '"Shadow Demon"', "80": '"Lone Druid"', "81": '"Chaos Knight"', "82": '"Meepo"', "83": '"Treant Protector"', "84": '"Ogre Magi"', "85": '"Undying"', "86": '"Rubick"', "87": '"Disruptor"', "88": '"Nyx Assassin"', "89": '"Naga Siren"', "90": '"Keeper of the Light"', "91": '"Io"', "92": '"Visage"', "93": '"Slark"', "94": '"Medusa"', "95": '"Troll Warlord"', "96": '"Centaur Warrunner"', "97": '"Magnus"', "98": '"Timbersaw"', "99": '"Bristleback"', "100": '"Tusk"', "101": '"Skywrath Mage"', "102": '"Abaddon"', "103": '"Elder Titan"', "104": '"Legion Commander"', "105": '"Techies"', "106": '"Ember Spirit"', "107": '"Earth Spirit"', "108": '"Underlord"', "109": '"Terrorblade"', "110": '"Phoenix"', "111": '"Oracle"', "112": '"Winter Wyvern"', "113": '"Arc Warden"', "114": '"Monkey King"', "119": '"Dark Willow"', "120": '"Pangolier"', "121": '"Grimstroke"', "123": '"Hoodwink"', "126": '"Void Spirit"', "128": '"Snapfire"', "129": '"Mars"', "131": '"Ring Master"', "135": '"Dawnbreaker"', "136": '"Marci"', "137": '"Primal Beast"', "138": '"Muerta"', "145": '"Kez"', "155": '"Largo"' }, broadcast: { WIN_NEGATIVE: `"Won the match by sheer luck", "Won the match by a stroke of bad luck", "Coasted to victory", "Didn't even show up for the team fight, but my teammates won 4v5"`, WIN_POSITIVE: '"Led the team to victory", "Dominated the opponents and secured the win", "Carried the game to victory", "Treated the opponents like pigs and won", "Won again; this game is just so monotonous and dull", "Simply achieved a win in