diff --git a/.doclets.yml b/.doclets.yml index ace095af..97c8041c 100644 --- a/.doclets.yml +++ b/.doclets.yml @@ -1,6 +1,19 @@ files: - index.js -dir: handlers + - handlers/cache.js + - handlers/chat.js + - handlers/community.js + - handlers/custom.js + - handlers/fantasy.js + - handlers/general.js + - handlers/helper.js + - handlers/inventory.js + - handlers/leagues.js + - handlers/lobbies.js + - handlers/match.js + - handlers/parties.js + - handlers/sourcetv.js + - handlers/team.js packageJson: package.json branches: - - doc \ No newline at end of file + - staging \ No newline at end of file diff --git a/.npmignore b/.npmignore index 00a42680..64397fbf 100644 --- a/.npmignore +++ b/.npmignore @@ -6,4 +6,5 @@ test sentry servers *.log -update_proto.sh \ No newline at end of file +update_proto.sh +*.hbs \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 13c00a1c..7c181ba2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ language: node_js node_js: - - "7.2.0" - - "6.9.1" + - "7.6.0" + - "6.10.0" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..4dd564d6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,76 @@ +# Changelog +## General +* examples will no longer be pushed to npm + +## Dependency changes +* Deleted the dependency on bignumber.js and replaced it by Long.js since protobufjs uses it. + +## API changes +### Methods +#### ToSteamID +Now returns a Long value instead of a string. + +#### sendMessage +Order of the parameters has changed to `(message, channel_name, channel_type)`. + +#### rollDice +Order of the parameters has changed to `(min, max, channel_name, channel_type)`. + +#### ServerRegion +This enum used to be defined both on module level and as a member of Dota2Client. +We removed the member definition and only kept the module level one, +in correspondence with all other enums. + +#### setItemPositions +Changed the parameter type from an array of tuples to an array of objects + +#### createPracticeLobby +Changed parameters to `(options, callback)` to reduce confusion. CreateTournamentLobby is now deprecated. + +### Events +#### matchesData +Event parameters are now `(request_id, total_results, results_remaining, matches, series)` + +#### practiceLobbyListData +Removed the null parameter + +#### friendPracticeLobbyListData +Removed the null parameter + +## Deprecation +There's a whole series of functions for which the GC hasn't responded in a long time. +Some of those were already deprecated since the last release, some of them have become deprecated since. +Those who were already deprecated for a long time have been deleted from the API. +Those who have become deprecated since the last release have been tagged deprecated. + +Deprecated methods will no longer figure in the documentation (mainly because they're +now auto-magically generated based on the code comments and I really don't feel +like adding copious amounts of documentation to a bunch of methods who no longer +can be used - shoot me). If they were one day to be re-enabled by Valve, these +will ofcourse be documented again. + +### Deleted methods +* requestProfile +* requestPassportData +* requestTeamProfile +* requestTeamMemberProfile +* requestTeamIDByName + +### Deleted events +* profileData +* passportData +* teamProfile +* teamID + +### Deprecated methods +* requestProTeamList +* requestGuildData +* inviteToGuild +* cancelInviteToGuild +* setGuildAccountRole + +### Deprecated events +* guildOpenPartyData +* guildData +* guildInviteData +* proTeamListData diff --git a/README.hbs b/README.hbs new file mode 100644 index 00000000..5173d8c4 --- /dev/null +++ b/README.hbs @@ -0,0 +1,52 @@ +node-dota2 +======== + +[![NPM version](https://img.shields.io/npm/v/dota2.svg)](https://npmjs.org/package/dota2 "View this project on NPM") +[![Build Status](https://img.shields.io/travis/Arcana/node-dota2.svg)](https://travis-ci.org/Arcana/node-dota2 "View this project's build information") +[![Dependency Status](https://img.shields.io/david/Arcana/node-dota2.svg)](https://david-dm.org/Arcana/node-dota2 "Check this project's dependencies") + +A node-steam plugin for Dota 2, consider it in alpha state. + +Check out RJackson1's blog post (his only blog post), [Extending node-dota2](https://blog.rjackson.me/extending-node-dota2/), for a rough overview of adding new functionality to the library. +A fair warning, while the way you search for new functionality is still the same, quite a lot has changed (and been simplified) implementation wise. +It is now easier to implement new functionality than it was back when this blog was written. + +## Installation and setup +* `npm install` in the repository root +* Copy `config.js.example` to `config.js` and edit appropriately +* Run the example script: `node example.js` +* If you receive Error 63 you need to provide a Steam Guard code by setting the Steam Guard code in `config.js` and launching again. +* Make sure to use at least version 4.4.5 of node js + +## Initializing +Parameters: +* `steamClient` - Pass a SteamClient instance to use to send & receive GC messages. +* `debug` - A boolean noting whether to print information about operations to console. +* `debugMore` - A boolean noting whether to print extended debug information. Activating this will log messages for each proto message exchanged with the GC. + +```js +var Steam = require('steam'), + steamClient = new Steam.SteamClient(), + dota2 = require('dota2'), + Dota2 = new dota2.Dota2Client(steamClient, true, false); +``` + +## Disclaimer +We do not in any way encourage people to use their own accounts when using this library. +This library tries to mimic the behavior of the Dota 2 client to allow people to programmatically interact with the Dota 2 GC, +however we make no efforts to hide this fact and it's pretty easy for Valve to detect clients using this library based on the generated traffic. +While Valve has not yet expressed a dislike regarding reverse engineering projects like this one, +it's not unimaginable that this might one day change and result in VAC bans. + +## Examples +The `examples` directory contains two Dota2 bots as an example. One contains commented-out dota2 methods, the other has boolean activated methods. +Both examples show how to interact with the library. + +## Testing +There is a partial automated test suite for node-dota2, which is located in the test directory. +You need to configure the `STEAM_USERNAME` and `STEAM_PASSWORD` environment variables to be able to run it. +You can launch the tests by running the file with mocha. + +# API +The API doc can be consulted here or at [doclets.io](https://doclets.io/Arcana/node-dota2) +{{>main}} diff --git a/README.md b/README.md index 583fa695..1a25a36a 100644 --- a/README.md +++ b/README.md @@ -11,23 +11,8 @@ Check out RJackson1's blog post (his only blog post), [Extending node-dota2](htt A fair warning, while the way you search for new functionality is still the same, quite a lot has changed (and been simplified) implementation wise. It is now easier to implement new functionality than it was back when this blog was written. -## Upgrade guide - -### `3.*.*` to `4.*.0` - -A few backwards incompatible API changes were included with version 4.0.0. - -* The following functions are no longer supported by Valve so they have been commented: - * `requestPassportData` - * `requestTeamProfile` - * `requestTeamIDByName` - * `requestTeamMemberProfile` -* The `teamData` event now throws an extra parameter `league_id` -* The `matchMakingStatsData` event's first two parameters changed as the old values no longer exist. -* The `matchMinimalDetailsData` event now returns the `last_match` bool as first argument. - ## Installation and setup -* `npm install steam; npm install` in the repository root (install Steam first to work around a node-steam#222) +* `npm install` in the repository root * Copy `config.js.example` to `config.js` and edit appropriately * Run the example script: `node example.js` * If you receive Error 63 you need to provide a Steam Guard code by setting the Steam Guard code in `config.js` and launching again. @@ -47,1020 +32,1889 @@ var Steam = require('steam'), ``` ## Disclaimer -We do not in any way encourage people to use their own accounts when using this library. -This library tries to mimic the behavior of the Dota 2 client to allow people to programmatically interact with the Dota 2 GC, -however we make no efforts to hide this fact and it's pretty easy for Valve to detect clients using this library based on the generated traffic. -While Valve has not yet expressed a dislike regarding reverse engineering projects like this one, +We do not in any way encourage people to use their own accounts when using this library. +This library tries to mimic the behavior of the Dota 2 client to allow people to programmatically interact with the Dota 2 GC, +however we make no efforts to hide this fact and it's pretty easy for Valve to detect clients using this library based on the generated traffic. +While Valve has not yet expressed a dislike regarding reverse engineering projects like this one, it's not unimaginable that this might one day change and result in VAC bans. ## Examples -The `examples` directory contains two Dota2 bots as an example. One contains commented-out dota2 methods, the other has boolean activated methods. +The `examples` directory contains two Dota2 bots as an example. One contains commented-out dota2 methods, the other has boolean activated methods. Both examples show how to interact with the library. ## Testing -There is a partial automated test suite for node-dota2, which is located in the test directory. +There is a partial automated test suite for node-dota2, which is located in the test directory. You need to configure the `STEAM_USERNAME` and `STEAM_PASSWORD` environment variables to be able to run it. You can launch the tests by running the file with mocha. -##Properties -###AccountID -The current steam ID of the SteamClient converted to Dota 2 Account ID format. Not available until `launch` is called. +# API +The API doc can be consulted here or at [doclets.io](https://doclets.io/Arcana/node-dota2) + + +## Dota2 +Dota 2 module + + +* [Dota2](#module_Dota2) + * _static_ + * [.Dota2Client](#module_Dota2.Dota2Client) ⇐ EventEmitter + * [new Dota2.Dota2Client(steamClient, debug, debugMore)](#new_module_Dota2.Dota2Client_new) + * _instance_ + * [.Inventory](#module_Dota2.Dota2Client+Inventory) : Array.<CSOEconItem> + * [.chatChannels](#module_Dota2.Dota2Client+chatChannels) : Array.<CMsgDOTAJoinChatChannelResponse> + * [.Lobby](#module_Dota2.Dota2Client+Lobby) : CSODOTALobby + * [.Options](#module_Dota2.Dota2Client+Lobby.Options) : Object + * [.LobbyInvite](#module_Dota2.Dota2Client+LobbyInvite) : CSODOTALobbyInvite + * [.Party](#module_Dota2.Dota2Client+Party) : CSODOTAParty + * [.PartyInvite](#module_Dota2.Dota2Client+PartyInvite) : CSODOTAPartyInvite + * [.launch()](#module_Dota2.Dota2Client+launch) + * [.exit()](#module_Dota2.Dota2Client+exit) + * [.joinChat(channel_name, [channel_type])](#module_Dota2.Dota2Client+joinChat) + * [.leaveChat(channel_name, [channel_type])](#module_Dota2.Dota2Client+leaveChat) + * [.sendMessage(message, channel_name, [channel_type])](#module_Dota2.Dota2Client+sendMessage) + * [.shareLobby(channel_name, [channel_type])](#module_Dota2.Dota2Client+shareLobby) + * [.flipCoin(channel_name, [channel_type])](#module_Dota2.Dota2Client+flipCoin) + * [.rollDice(min, max, channel_name, [channel_type])](#module_Dota2.Dota2Client+rollDice) + * [.requestChatChannels()](#module_Dota2.Dota2Client+requestChatChannels) + * [.requestPlayerMatchHistory(account_id, [options], [callback])](#module_Dota2.Dota2Client+requestPlayerMatchHistory) + * [.requestProfileCard(account_id, [callback])](#module_Dota2.Dota2Client+requestProfileCard) + * [.requestHallOfFame(week, [callback])](#module_Dota2.Dota2Client+requestHallOfFame) + * [.requestPlayerInfo(account_ids)](#module_Dota2.Dota2Client+requestPlayerInfo) + * [.requestTrophyList(account_id, [callback])](#module_Dota2.Dota2Client+requestTrophyList) + * [.requestPlayerStats(account_id, [callback])](#module_Dota2.Dota2Client+requestPlayerStats) + * [.requestJoinableCustomGameModes([server_region])](#module_Dota2.Dota2Client+requestJoinableCustomGameModes) + * [.requestPlayerCardsByPlayer()](#module_Dota2.Dota2Client+requestPlayerCardsByPlayer) ⇒ Array.<FantasyPlayer> + * [.FantasyPlayer](#module_Dota2.Dota2Client+requestPlayerCardsByPlayer.FantasyPlayer) : Object + * [.requestPlayerCardRoster(league_id, timestamp, [callback])](#module_Dota2.Dota2Client+requestPlayerCardRoster) + * [.draftPlayerCard(league_id, timestamp, slot, player_card_id, [callback])](#module_Dota2.Dota2Client+draftPlayerCard) + * [.setItemPositions(item_positions)](#module_Dota2.Dota2Client+setItemPositions) + * [.deleteItem(item_id)](#module_Dota2.Dota2Client+deleteItem) + * [.requestLeaguesInMonth([month], [year], [tier], [callback])](#module_Dota2.Dota2Client+requestLeaguesInMonth) + * [.requestLeagueInfo()](#module_Dota2.Dota2Client+requestLeagueInfo) + * [.requestTopLeagueMatches()](#module_Dota2.Dota2Client+requestTopLeagueMatches) + * [.createPracticeLobby(options, [callback])](#module_Dota2.Dota2Client+createPracticeLobby) + * ~~[._createPracticeLobby()](#module_Dota2.Dota2Client+_createPracticeLobby)~~ + * ~~[.createTournamentLobby()](#module_Dota2.Dota2Client+createTournamentLobby)~~ + * [.configPracticeLobby(lobby_id, options, [callback])](#module_Dota2.Dota2Client+configPracticeLobby) + * [.requestPracticeLobbyList([callback])](#module_Dota2.Dota2Client+requestPracticeLobbyList) + * [.requestFriendPracticeLobbyList([callback])](#module_Dota2.Dota2Client+requestFriendPracticeLobbyList) + * [.balancedShuffleLobby([callback])](#module_Dota2.Dota2Client+balancedShuffleLobby) + * [.flipLobbyTeams([callback])](#module_Dota2.Dota2Client+flipLobbyTeams) + * [.inviteToLobby(steam_id)](#module_Dota2.Dota2Client+inviteToLobby) + * [.practiceLobbyKick(account_id, [callback])](#module_Dota2.Dota2Client+practiceLobbyKick) + * [.practiceLobbyKickFromTeam(account_id, [callback])](#module_Dota2.Dota2Client+practiceLobbyKickFromTeam) + * [.joinPracticeLobby(id, password, [callback])](#module_Dota2.Dota2Client+joinPracticeLobby) + * [.leavePracticeLobby([callback])](#module_Dota2.Dota2Client+leavePracticeLobby) + * [.abandonCurrentGame([callback])](#module_Dota2.Dota2Client+abandonCurrentGame) + * [.launchPracticeLobby([callback])](#module_Dota2.Dota2Client+launchPracticeLobby) + * [.joinPracticeLobbyTeam(slot, team, [callback])](#module_Dota2.Dota2Client+joinPracticeLobbyTeam) + * [.joinPracticeLobbyBroadcastChannel([channel], [callback])](#module_Dota2.Dota2Client+joinPracticeLobbyBroadcastChannel) + * [.addBotToPracticeLobby(slot, team, bot_difficulty, [callback])](#module_Dota2.Dota2Client+addBotToPracticeLobby) + * [.respondLobbyInvite(id, accept)](#module_Dota2.Dota2Client+respondLobbyInvite) + * [.requestMatches([criteria], [callback])](#module_Dota2.Dota2Client+requestMatches) + * [.requestMatchDetails(match_ids, [callback])](#module_Dota2.Dota2Client+requestMatchDetails) + * [.requestMatchMinimalDetails(match_id, [callback])](#module_Dota2.Dota2Client+requestMatchMinimalDetails) + * [.requestMatchmakingStats()](#module_Dota2.Dota2Client+requestMatchmakingStats) + * [.requestTopFriendMatches()](#module_Dota2.Dota2Client+requestTopFriendMatches) + * [.respondPartyInvite(id, [accept], [ping_data])](#module_Dota2.Dota2Client+respondPartyInvite) + * [.leaveParty()](#module_Dota2.Dota2Client+leaveParty) + * [.setPartyLeader(steam_id)](#module_Dota2.Dota2Client+setPartyLeader) + * [.setPartyCoach(coach)](#module_Dota2.Dota2Client+setPartyCoach) + * [.inviteToParty(steam_id)](#module_Dota2.Dota2Client+inviteToParty) + * [.kickFromParty(steam_id)](#module_Dota2.Dota2Client+kickFromParty) + * [.requestSourceTVGames(filter_options)](#module_Dota2.Dota2Client+requestSourceTVGames) + * [.requestMyTeams([callback])](#module_Dota2.Dota2Client+requestMyTeams) + * ["ready"](#module_Dota2.Dota2Client+event_ready) + * ["unhandled" (kMsg, kMsg_name)](#module_Dota2.Dota2Client+event_unhandled) + * ["hellotimeout"](#module_Dota2.Dota2Client+event_hellotimeout) + * ["inventoryUpdate" (inventory)](#module_Dota2.Dota2Client+event_inventoryUpdate) + * ["practiceLobbyUpdate" (lobby)](#module_Dota2.Dota2Client+event_practiceLobbyUpdate) + * ["practiceLobbyCleared"](#module_Dota2.Dota2Client+event_practiceLobbyCleared) + * ["lobbyInviteUpdate" (lobbyInvite)](#module_Dota2.Dota2Client+event_lobbyInviteUpdate) + * ["lobbyInviteCleared"](#module_Dota2.Dota2Client+event_lobbyInviteCleared) + * ["partyUpdate" (party)](#module_Dota2.Dota2Client+event_partyUpdate) + * ["partyCleared"](#module_Dota2.Dota2Client+event_partyCleared) + * ["partyInviteUpdate" (partyInvite)](#module_Dota2.Dota2Client+event_partyInviteUpdate) + * ["partyInviteCleared"](#module_Dota2.Dota2Client+event_partyInviteCleared) + * ["chatJoined" (channelData)](#module_Dota2.Dota2Client+event_chatJoined) + * ["chatJoin" (channel, joiner_name, joiner_steam_id, otherJoined_object)](#module_Dota2.Dota2Client+event_chatJoin) + * ["chatLeave" (channel, leaver_steam_id, otherLeft_object)](#module_Dota2.Dota2Client+event_chatLeave) + * ["chatMessage" (channel, sender_name, message, chatData)](#module_Dota2.Dota2Client+event_chatMessage) + * ["chatChannelsData" (channels)](#module_Dota2.Dota2Client+event_chatChannelsData) + * ["playerMatchHistoryData" (requestId, matchHistoryResponse)](#module_Dota2.Dota2Client+event_playerMatchHistoryData) + * ["profileCardData" (account_id, profileCardResponse)](#module_Dota2.Dota2Client+event_profileCardData) + * ["hallOfFameData" (week, featured_players, featured_farmer, hallOfFameResponse)](#module_Dota2.Dota2Client+event_hallOfFameData) + * ["playerInfoData" (playerInfoData)](#module_Dota2.Dota2Client+event_playerInfoData) + * ["trophyListData" (trophyListResponse)](#module_Dota2.Dota2Client+event_trophyListData) + * ["playerStatsData" (account_id, playerStatsResponse)](#module_Dota2.Dota2Client+event_playerStatsData) + * ["joinableCustomGameModes" (joinableCustomGameModes)](#module_Dota2.Dota2Client+event_joinableCustomGameModes) + * ["playerCardRoster" (playerCardRoster)](#module_Dota2.Dota2Client+event_playerCardRoster) + * ["playerCardDrafted" (playerCardRoster)](#module_Dota2.Dota2Client+event_playerCardDrafted) + * ["popup" (id, popup)](#module_Dota2.Dota2Client+event_popup) + * ["leaguesInMonthData" (month, year, leagues)](#module_Dota2.Dota2Client+event_leaguesInMonthData) + * ["liveLeagueGamesUpdate" (live_league_games)](#module_Dota2.Dota2Client+event_liveLeagueGamesUpdate) + * ["leagueData" (leagues)](#module_Dota2.Dota2Client+event_leagueData) + * ["topLeagueMatchesData" (matches)](#module_Dota2.Dota2Client+event_topLeagueMatchesData) + * ["practiceLobbyJoinResponse" (result, response)](#module_Dota2.Dota2Client+event_practiceLobbyJoinResponse) + * ["practiceLobbyListData" (practiceLobbyListResponse)](#module_Dota2.Dota2Client+event_practiceLobbyListData) + * ["practiceLobbyResponse" (result, response)](#module_Dota2.Dota2Client+event_practiceLobbyResponse) + * ["friendPracticeLobbyListData" (practiceLobbyListResponse)](#module_Dota2.Dota2Client+event_friendPracticeLobbyListData) + * ["inviteCreated" (steam_id, group_id, is_online)](#module_Dota2.Dota2Client+event_inviteCreated) + * ["matchesData" (requestId, total_results, results_remaining, matches, series, matchResponse)](#module_Dota2.Dota2Client+event_matchesData) + * ["matchDetailsData" (match_id, matchDetailsResponse)](#module_Dota2.Dota2Client+event_matchDetailsData) + * ["matchMinimalDetailsData" (last_match, matchMinimalDetailsResponse)](#module_Dota2.Dota2Client+event_matchMinimalDetailsData) + * ["matchmakingStatsData" (matchgroups_version, match_groups, matchmakingStatsResponse)](#module_Dota2.Dota2Client+event_matchmakingStatsData) + * ["topFriendMatchesData" (matches)](#module_Dota2.Dota2Client+event_topFriendMatchesData) + * ["sourceTVGamesData" (sourceTVGamesResponse)](#module_Dota2.Dota2Client+event_sourceTVGamesData) + * ["teamData" (teams, league_id)](#module_Dota2.Dota2Client+event_teamData) + * _static_ + * [.ToAccountID(steamID)](#module_Dota2.Dota2Client.ToAccountID) ⇒ number + * [.ToSteamID(accid)](#module_Dota2.Dota2Client.ToSteamID) ⇒ [Long](#external_Long) + * [.schema](#module_Dota2.schema) + * [.CMsgGCToClientPlayerStatsResponse](#module_Dota2.schema.CMsgGCToClientPlayerStatsResponse) : Object + * [.EResult](#module_Dota2.EResult) : enum + * [.ServerRegion](#module_Dota2.ServerRegion) : enum + * [.SeriesType](#module_Dota2.SeriesType) : enum + * [.BotDifficulty](#module_Dota2.BotDifficulty) : enum + * _inner_ + * [~requestCallback](#module_Dota2..requestCallback) : function + * [~Long](#external_Long) + + + +### Dota2.Dota2Client ⇐ EventEmitter +**Kind**: static class of [Dota2](#module_Dota2) +**Extends:** EventEmitter +**Emits**: [ready](#module_Dota2.Dota2Client+event_ready), [unhandled](#module_Dota2.Dota2Client+event_unhandled), [hellotimeout](#module_Dota2.Dota2Client+event_hellotimeout), [popup](#module_Dota2.Dota2Client+event_popup), [sourceTVGamesData](#module_Dota2.Dota2Client+event_sourceTVGamesData), [inventoryUpdate](#module_Dota2.Dota2Client+event_inventoryUpdate), [practiceLobbyUpdate](#module_Dota2.Dota2Client+event_practiceLobbyUpdate), [practiceLobbyCleared](#module_Dota2.Dota2Client+event_practiceLobbyCleared), [lobbyInviteUpdate](#module_Dota2.Dota2Client+event_lobbyInviteUpdate), [lobbyInviteCleared](#module_Dota2.Dota2Client+event_lobbyInviteCleared), [practiceLobbyJoinResponse](#module_Dota2.Dota2Client+event_practiceLobbyJoinResponse), [practiceLobbyListData](#module_Dota2.Dota2Client+event_practiceLobbyListData), [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse), [friendPracticeLobbyListData](#module_Dota2.Dota2Client+event_friendPracticeLobbyListData), [inviteCreated](#module_Dota2.Dota2Client+event_inviteCreated), [partyUpdate](#module_Dota2.Dota2Client+event_partyUpdate), [partyCleared](#module_Dota2.Dota2Client+event_partyCleared), [partyInviteUpdate](#module_Dota2.Dota2Client+event_partyInviteUpdate), [partyInviteCleared](#module_Dota2.Dota2Client+event_partyInviteCleared), [joinableCustomGameModes](#module_Dota2.Dota2Client+event_joinableCustomGameModes), [chatChannelsData](#module_Dota2.Dota2Client+event_chatChannelsData), [chatJoin](#module_Dota2.Dota2Client+event_chatJoin), [chatJoined](#module_Dota2.Dota2Client+event_chatJoined), [chatLeave](#module_Dota2.Dota2Client+event_chatLeave), [chatMessage](#module_Dota2.Dota2Client+event_chatMessage), [profileCardData](#module_Dota2.Dota2Client+event_profileCardData), [playerMatchHistoryData](#module_Dota2.Dota2Client+event_playerMatchHistoryData), [playerInfoData](#module_Dota2.Dota2Client+event_playerInfoData), [playerStatsData](#module_Dota2.Dota2Client+event_playerStatsData), [trophyListData](#module_Dota2.Dota2Client+event_trophyListData), [hallOfFameData](#module_Dota2.Dota2Client+event_hallOfFameData), [playerCardRoster](#module_Dota2.Dota2Client+event_playerCardRoster), [playerCardDrafted](#module_Dota2.Dota2Client+event_playerCardDrafted), [leaguesInMonthData](#module_Dota2.Dota2Client+event_leaguesInMonthData), [liveLeagueGamesUpdate](#module_Dota2.Dota2Client+event_liveLeagueGamesUpdate), [leagueData](#module_Dota2.Dota2Client+event_leagueData), [topLeagueMatchesData](#module_Dota2.Dota2Client+event_topLeagueMatchesData), [teamData](#module_Dota2.Dota2Client+event_teamData), [matchesData](#module_Dota2.Dota2Client+event_matchesData), [matchDetailsData](#module_Dota2.Dota2Client+event_matchDetailsData), [matchMinimalDetailsData](#module_Dota2.Dota2Client+event_matchMinimalDetailsData), [matchmakingStatsData](#module_Dota2.Dota2Client+event_matchmakingStatsData), [topFriendMatchesData](#module_Dota2.Dota2Client+event_topFriendMatchesData) + +* [.Dota2Client](#module_Dota2.Dota2Client) ⇐ EventEmitter + * [new Dota2.Dota2Client(steamClient, debug, debugMore)](#new_module_Dota2.Dota2Client_new) + * _instance_ + * [.Inventory](#module_Dota2.Dota2Client+Inventory) : Array.<CSOEconItem> + * [.chatChannels](#module_Dota2.Dota2Client+chatChannels) : Array.<CMsgDOTAJoinChatChannelResponse> + * [.Lobby](#module_Dota2.Dota2Client+Lobby) : CSODOTALobby + * [.Options](#module_Dota2.Dota2Client+Lobby.Options) : Object + * [.LobbyInvite](#module_Dota2.Dota2Client+LobbyInvite) : CSODOTALobbyInvite + * [.Party](#module_Dota2.Dota2Client+Party) : CSODOTAParty + * [.PartyInvite](#module_Dota2.Dota2Client+PartyInvite) : CSODOTAPartyInvite + * [.launch()](#module_Dota2.Dota2Client+launch) + * [.exit()](#module_Dota2.Dota2Client+exit) + * [.joinChat(channel_name, [channel_type])](#module_Dota2.Dota2Client+joinChat) + * [.leaveChat(channel_name, [channel_type])](#module_Dota2.Dota2Client+leaveChat) + * [.sendMessage(message, channel_name, [channel_type])](#module_Dota2.Dota2Client+sendMessage) + * [.shareLobby(channel_name, [channel_type])](#module_Dota2.Dota2Client+shareLobby) + * [.flipCoin(channel_name, [channel_type])](#module_Dota2.Dota2Client+flipCoin) + * [.rollDice(min, max, channel_name, [channel_type])](#module_Dota2.Dota2Client+rollDice) + * [.requestChatChannels()](#module_Dota2.Dota2Client+requestChatChannels) + * [.requestPlayerMatchHistory(account_id, [options], [callback])](#module_Dota2.Dota2Client+requestPlayerMatchHistory) + * [.requestProfileCard(account_id, [callback])](#module_Dota2.Dota2Client+requestProfileCard) + * [.requestHallOfFame(week, [callback])](#module_Dota2.Dota2Client+requestHallOfFame) + * [.requestPlayerInfo(account_ids)](#module_Dota2.Dota2Client+requestPlayerInfo) + * [.requestTrophyList(account_id, [callback])](#module_Dota2.Dota2Client+requestTrophyList) + * [.requestPlayerStats(account_id, [callback])](#module_Dota2.Dota2Client+requestPlayerStats) + * [.requestJoinableCustomGameModes([server_region])](#module_Dota2.Dota2Client+requestJoinableCustomGameModes) + * [.requestPlayerCardsByPlayer()](#module_Dota2.Dota2Client+requestPlayerCardsByPlayer) ⇒ Array.<FantasyPlayer> + * [.FantasyPlayer](#module_Dota2.Dota2Client+requestPlayerCardsByPlayer.FantasyPlayer) : Object + * [.requestPlayerCardRoster(league_id, timestamp, [callback])](#module_Dota2.Dota2Client+requestPlayerCardRoster) + * [.draftPlayerCard(league_id, timestamp, slot, player_card_id, [callback])](#module_Dota2.Dota2Client+draftPlayerCard) + * [.setItemPositions(item_positions)](#module_Dota2.Dota2Client+setItemPositions) + * [.deleteItem(item_id)](#module_Dota2.Dota2Client+deleteItem) + * [.requestLeaguesInMonth([month], [year], [tier], [callback])](#module_Dota2.Dota2Client+requestLeaguesInMonth) + * [.requestLeagueInfo()](#module_Dota2.Dota2Client+requestLeagueInfo) + * [.requestTopLeagueMatches()](#module_Dota2.Dota2Client+requestTopLeagueMatches) + * [.createPracticeLobby(options, [callback])](#module_Dota2.Dota2Client+createPracticeLobby) + * ~~[._createPracticeLobby()](#module_Dota2.Dota2Client+_createPracticeLobby)~~ + * ~~[.createTournamentLobby()](#module_Dota2.Dota2Client+createTournamentLobby)~~ + * [.configPracticeLobby(lobby_id, options, [callback])](#module_Dota2.Dota2Client+configPracticeLobby) + * [.requestPracticeLobbyList([callback])](#module_Dota2.Dota2Client+requestPracticeLobbyList) + * [.requestFriendPracticeLobbyList([callback])](#module_Dota2.Dota2Client+requestFriendPracticeLobbyList) + * [.balancedShuffleLobby([callback])](#module_Dota2.Dota2Client+balancedShuffleLobby) + * [.flipLobbyTeams([callback])](#module_Dota2.Dota2Client+flipLobbyTeams) + * [.inviteToLobby(steam_id)](#module_Dota2.Dota2Client+inviteToLobby) + * [.practiceLobbyKick(account_id, [callback])](#module_Dota2.Dota2Client+practiceLobbyKick) + * [.practiceLobbyKickFromTeam(account_id, [callback])](#module_Dota2.Dota2Client+practiceLobbyKickFromTeam) + * [.joinPracticeLobby(id, password, [callback])](#module_Dota2.Dota2Client+joinPracticeLobby) + * [.leavePracticeLobby([callback])](#module_Dota2.Dota2Client+leavePracticeLobby) + * [.abandonCurrentGame([callback])](#module_Dota2.Dota2Client+abandonCurrentGame) + * [.launchPracticeLobby([callback])](#module_Dota2.Dota2Client+launchPracticeLobby) + * [.joinPracticeLobbyTeam(slot, team, [callback])](#module_Dota2.Dota2Client+joinPracticeLobbyTeam) + * [.joinPracticeLobbyBroadcastChannel([channel], [callback])](#module_Dota2.Dota2Client+joinPracticeLobbyBroadcastChannel) + * [.addBotToPracticeLobby(slot, team, bot_difficulty, [callback])](#module_Dota2.Dota2Client+addBotToPracticeLobby) + * [.respondLobbyInvite(id, accept)](#module_Dota2.Dota2Client+respondLobbyInvite) + * [.requestMatches([criteria], [callback])](#module_Dota2.Dota2Client+requestMatches) + * [.requestMatchDetails(match_ids, [callback])](#module_Dota2.Dota2Client+requestMatchDetails) + * [.requestMatchMinimalDetails(match_id, [callback])](#module_Dota2.Dota2Client+requestMatchMinimalDetails) + * [.requestMatchmakingStats()](#module_Dota2.Dota2Client+requestMatchmakingStats) + * [.requestTopFriendMatches()](#module_Dota2.Dota2Client+requestTopFriendMatches) + * [.respondPartyInvite(id, [accept], [ping_data])](#module_Dota2.Dota2Client+respondPartyInvite) + * [.leaveParty()](#module_Dota2.Dota2Client+leaveParty) + * [.setPartyLeader(steam_id)](#module_Dota2.Dota2Client+setPartyLeader) + * [.setPartyCoach(coach)](#module_Dota2.Dota2Client+setPartyCoach) + * [.inviteToParty(steam_id)](#module_Dota2.Dota2Client+inviteToParty) + * [.kickFromParty(steam_id)](#module_Dota2.Dota2Client+kickFromParty) + * [.requestSourceTVGames(filter_options)](#module_Dota2.Dota2Client+requestSourceTVGames) + * [.requestMyTeams([callback])](#module_Dota2.Dota2Client+requestMyTeams) + * ["ready"](#module_Dota2.Dota2Client+event_ready) + * ["unhandled" (kMsg, kMsg_name)](#module_Dota2.Dota2Client+event_unhandled) + * ["hellotimeout"](#module_Dota2.Dota2Client+event_hellotimeout) + * ["inventoryUpdate" (inventory)](#module_Dota2.Dota2Client+event_inventoryUpdate) + * ["practiceLobbyUpdate" (lobby)](#module_Dota2.Dota2Client+event_practiceLobbyUpdate) + * ["practiceLobbyCleared"](#module_Dota2.Dota2Client+event_practiceLobbyCleared) + * ["lobbyInviteUpdate" (lobbyInvite)](#module_Dota2.Dota2Client+event_lobbyInviteUpdate) + * ["lobbyInviteCleared"](#module_Dota2.Dota2Client+event_lobbyInviteCleared) + * ["partyUpdate" (party)](#module_Dota2.Dota2Client+event_partyUpdate) + * ["partyCleared"](#module_Dota2.Dota2Client+event_partyCleared) + * ["partyInviteUpdate" (partyInvite)](#module_Dota2.Dota2Client+event_partyInviteUpdate) + * ["partyInviteCleared"](#module_Dota2.Dota2Client+event_partyInviteCleared) + * ["chatJoined" (channelData)](#module_Dota2.Dota2Client+event_chatJoined) + * ["chatJoin" (channel, joiner_name, joiner_steam_id, otherJoined_object)](#module_Dota2.Dota2Client+event_chatJoin) + * ["chatLeave" (channel, leaver_steam_id, otherLeft_object)](#module_Dota2.Dota2Client+event_chatLeave) + * ["chatMessage" (channel, sender_name, message, chatData)](#module_Dota2.Dota2Client+event_chatMessage) + * ["chatChannelsData" (channels)](#module_Dota2.Dota2Client+event_chatChannelsData) + * ["playerMatchHistoryData" (requestId, matchHistoryResponse)](#module_Dota2.Dota2Client+event_playerMatchHistoryData) + * ["profileCardData" (account_id, profileCardResponse)](#module_Dota2.Dota2Client+event_profileCardData) + * ["hallOfFameData" (week, featured_players, featured_farmer, hallOfFameResponse)](#module_Dota2.Dota2Client+event_hallOfFameData) + * ["playerInfoData" (playerInfoData)](#module_Dota2.Dota2Client+event_playerInfoData) + * ["trophyListData" (trophyListResponse)](#module_Dota2.Dota2Client+event_trophyListData) + * ["playerStatsData" (account_id, playerStatsResponse)](#module_Dota2.Dota2Client+event_playerStatsData) + * ["joinableCustomGameModes" (joinableCustomGameModes)](#module_Dota2.Dota2Client+event_joinableCustomGameModes) + * ["playerCardRoster" (playerCardRoster)](#module_Dota2.Dota2Client+event_playerCardRoster) + * ["playerCardDrafted" (playerCardRoster)](#module_Dota2.Dota2Client+event_playerCardDrafted) + * ["popup" (id, popup)](#module_Dota2.Dota2Client+event_popup) + * ["leaguesInMonthData" (month, year, leagues)](#module_Dota2.Dota2Client+event_leaguesInMonthData) + * ["liveLeagueGamesUpdate" (live_league_games)](#module_Dota2.Dota2Client+event_liveLeagueGamesUpdate) + * ["leagueData" (leagues)](#module_Dota2.Dota2Client+event_leagueData) + * ["topLeagueMatchesData" (matches)](#module_Dota2.Dota2Client+event_topLeagueMatchesData) + * ["practiceLobbyJoinResponse" (result, response)](#module_Dota2.Dota2Client+event_practiceLobbyJoinResponse) + * ["practiceLobbyListData" (practiceLobbyListResponse)](#module_Dota2.Dota2Client+event_practiceLobbyListData) + * ["practiceLobbyResponse" (result, response)](#module_Dota2.Dota2Client+event_practiceLobbyResponse) + * ["friendPracticeLobbyListData" (practiceLobbyListResponse)](#module_Dota2.Dota2Client+event_friendPracticeLobbyListData) + * ["inviteCreated" (steam_id, group_id, is_online)](#module_Dota2.Dota2Client+event_inviteCreated) + * ["matchesData" (requestId, total_results, results_remaining, matches, series, matchResponse)](#module_Dota2.Dota2Client+event_matchesData) + * ["matchDetailsData" (match_id, matchDetailsResponse)](#module_Dota2.Dota2Client+event_matchDetailsData) + * ["matchMinimalDetailsData" (last_match, matchMinimalDetailsResponse)](#module_Dota2.Dota2Client+event_matchMinimalDetailsData) + * ["matchmakingStatsData" (matchgroups_version, match_groups, matchmakingStatsResponse)](#module_Dota2.Dota2Client+event_matchmakingStatsData) + * ["topFriendMatchesData" (matches)](#module_Dota2.Dota2Client+event_topFriendMatchesData) + * ["sourceTVGamesData" (sourceTVGamesResponse)](#module_Dota2.Dota2Client+event_sourceTVGamesData) + * ["teamData" (teams, league_id)](#module_Dota2.Dota2Client+event_teamData) + * _static_ + * [.ToAccountID(steamID)](#module_Dota2.Dota2Client.ToAccountID) ⇒ number + * [.ToSteamID(accid)](#module_Dota2.Dota2Client.ToSteamID) ⇒ [Long](#external_Long) + + + +#### new Dota2.Dota2Client(steamClient, debug, debugMore) +The Dota 2 client that communicates with the GC + + +| Param | Type | Description | +| --- | --- | --- | +| steamClient | Object | Node-steam client instance | +| debug | boolean | Print debug information to console | +| debugMore | boolean | Print even more debug information to console | + + + +#### dota2Client.Inventory : Array.<CSOEconItem> +The current state of the bot's inventory. Contains cosmetics, player cards, ... + +**Kind**: instance property of [Dota2Client](#module_Dota2.Dota2Client) + + +#### dota2Client.chatChannels : Array.<CMsgDOTAJoinChatChannelResponse> +The chat channels the bot has joined + +**Kind**: instance property of [Dota2Client](#module_Dota2.Dota2Client) + + +#### dota2Client.Lobby : CSODOTALobby +The lobby the bot is currently in. Falsy if the bot isn't in a lobby. + +**Kind**: instance property of [Dota2Client](#module_Dota2.Dota2Client) + + +##### Lobby.Options : Object +**Kind**: static typedef of [Lobby](#module_Dota2.Dota2Client+Lobby) +**Properties** + +| Name | Type | Default | Description | +| --- | --- | --- | --- | +| game_name | string | | Name of the lobby | +| pass_key | string | | Lobby password | +| server_region | [ServerRegion](#module_Dota2.ServerRegion) | module:Dota2.ServerRegion.UNSPECIFIED | Server region where the lobby will be created | +| game_mode | DOTA_GameMode | DOTA_GameMode.DOTA_GAMEMODE_AP | Game mode | +| game_version | DOTAGameVersion | DOTAGameVersion.GAME_VERSION_STABLE | Version of the game | +| cm_pick | DOTA_CM_PICK | DOTA_CM_PICK.DOTA_CM_RANDOM | Who gets first pick | +| allow_cheats | boolean | false | Whether or not to allow cheats | +| fill_with_bots | boolean | false | Whether or not to fill empty slots with bots | +| bot_difficulty_radiant | BotDifficulty | module:Dota2.BotDifficulty.PASSIVE | The bot difficulty for radiant bots, if fill_with_bots is true. | +| bot_difficulty_dire | BotDifficulty | module:Dota2.BotDifficulty.PASSIVE | The bot difficulty for dire bots, if fill_with_bots is true. | +| bot_radiant | number | | Presumably the ID of the custom AI to be applied to radiant bots. | +| bot_dire | number | | Presumably the ID of the custom AI to be applied to dire bots. | +| allow_spectating | boolean | true | Whether or not to allow spectating | +| series_type | SeriesType | NONE | Whether or not the game is part of a series (Bo3, Bo5). | +| radiant_series_wins | number | 0 | # of games won so far, e.g. for a Bo3 or Bo5. | +| dire_series_wins | number | 0 | # of games won so far, e.g. for a Bo3 or Bo5. | +| previous_match_override | number | | In a series, the match ID of the previous game. If not supplied, the GC will try to find it automatically based on the teams and the players. | +| allchat | boolean | false | Whether or not it's allowed to all-chat | +| dota_tv_delay | LobbyDotaTVDelay | LobbyDotaTV_120 | How much time the game should be delayed for DotaTV. | +| leagueid | number | | The league this lobby is being created for. The bot should be a league admin for this to work. | +| custom_game_mode | string | | Name of the custom game | +| custom_map_name | string | | Which map the custom game should be played on | +| custom_difficulty | number | | Difficulty of the custom game | +| custom_game_id | [Long](#external_Long) | | 64bit ID of the custom game mode | + + + +#### dota2Client.LobbyInvite : CSODOTALobbyInvite +The currently active lobby invitation. Falsy if the bot has not been invited. + +**Kind**: instance property of [Dota2Client](#module_Dota2.Dota2Client) + + +#### dota2Client.Party : CSODOTAParty +The party the bot is currently in. Falsy if the bot isn't in a party. + +**Kind**: instance property of [Dota2Client](#module_Dota2.Dota2Client) + + +#### dota2Client.PartyInvite : CSODOTAPartyInvite +The currently active party invitation. Falsy if the bot has not been invited. + +**Kind**: instance property of [Dota2Client](#module_Dota2.Dota2Client) + + +#### dota2Client.launch() +Reports to Steam that you're playing Dota 2, and then initiates communication with the Game Coordinator. -###Inventory (hats, not in-match items) -The current player inventory (see CSOEconItem). Null if the bot hasn't received inventory information yet. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + -###Lobby -The current lobby object (see CSODOTALobby). Null if the bot is not in a lobby. +#### dota2Client.exit() +Stop sending a heartbeat to the GC and report to steam you're no longer playing Dota 2 -###Party -The current party object (see CSODOTAParty). Null if the bot is not in a party. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + -###PartyInvite -The current party invite object (see CSODOTAPartyInvite). Null if the bot does not have an active incoming party invite. +#### dota2Client.joinChat(channel_name, [channel_type]) +Joins a chat channel. If the chat channel with the given name doesn't exist, it +is created. Listen for the `chatMessage` event for other people's chat messages. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -###LobbyInvite -The current lobby invite object (see CSODOTALobbyInvite). Null if the bot does not have an active incoming lobby invite. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -## Methods -All methods require the SteamClient instance to be logged on. +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| channel_name | string | | Name of the chat channel | +| [channel_type] | DOTAChatChannelType_t | DOTAChatChannelType_t.DOTAChatChannelType_Custom | The type of the channel being joined | -### Steam -#### launch() + -Reports to Steam that you're playing Dota 2, and then initiates communication with the Game Coordinator. +#### dota2Client.leaveChat(channel_name, [channel_type]) +Leaves a chat channel. If you've joined different channels with the same name, +specify the type to prevent unexpected behaviour. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### exit() +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Tells Steam you were feeding. +| Param | Type | Description | +| --- | --- | --- | +| channel_name | string | Name of the chat channel | +| [channel_type] | DOTAChatChannelType_t | The type of the channel being joined | + -###Utilities -#### ToAccountID(steamID) -* Takes an input steam ID in any format and converts it into an int Account ID. +#### dota2Client.sendMessage(message, channel_name, [channel_type]) +Sends a message to the specified chat channel. Won't send if you're not in the channel you try to send to. +If you've joined different channels with the same name, specify the type to prevent unexpected behaviour. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### ToSteamID(accountID) -* Takes an input Dota 2 acount ID in any format and converts it into a string steam ID. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) +| Param | Type | Description | +| --- | --- | --- | +| message | string | The message you want to send | +| channel_name | string | Name of the chat channel | +| [channel_type] | DOTAChatChannelType_t | The type of the channel being joined | -### Inventory -#### setItemPositions(item_positions) -* `item_positions` - An array of tuples (itemid, position). + -Attempts to move items within your inventory to the positions you set. Requires the GC to be ready (listen for the `ready` event before calling). +#### dota2Client.shareLobby(channel_name, [channel_type]) +Shares the lobby you're currently in with the chat so other people can join. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### deleteItem(item_id) +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Attempts to delete an item. Requires the GC to be ready (listen for the `ready` event before calling). +| Param | Type | Description | +| --- | --- | --- | +| channel_name | string | Name of the chat channel | +| [channel_type] | DOTAChatChannelType_t | The type of the channel being joined | + -### Chat -**_In order to send a message, your account must 1. be non-Limited Steam Account 2. have at least 5 Trophy Level_** +#### dota2Client.flipCoin(channel_name, [channel_type]) +Sends a coin flip to the specified chat channel. Won't send if you're not in the channel you try to send to. +If you've joined different channels with the same name, specify the type to prevent unexpected behaviour. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### joinChat(channel_name, [channel_type]) -* `channel_name` - A string for the channel name. -* `[channel_type]` - The type of the channel being joined. Defaults to `Dota2.schema.DOTAChatChannelType_t.DOTAChannelType_Custom`. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Joins a chat channel. If the chat channel with the given name doesn't exist, it -is created. Listen for the `chatMessage` event for other people's chat messages. +| Param | Type | Description | +| --- | --- | --- | +| channel_name | string | Name of the chat channel | +| [channel_type] | DOTAChatChannelType_t | The type of the channel being joined | + + -Notable channels: -* `Guild_##########` - The chat channel of the guild with guild_id = ########## -* `Lobby_##########` - The chat channel of the lobby with lobby_id = ########## +#### dota2Client.rollDice(min, max, channel_name, [channel_type]) +Sends a dice roll to the specified chat channel. Won't send if you're not in the channel you try to send to. +If you've joined different channels with the same name, specify the type to prevent unexpected behaviour. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### leaveChat(channel_name, [channel_type]) -* `channel_name` - A string for the channel name. -* `[channel_type]` - The type of the channel you want to leave. Use the `Dota2.schema.DOTAChatChannelType_t` enum. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Leaves a chat channel. If you've joined different channels with the same name, specify the type to prevent unexpected behaviour. +| Param | Type | Description | +| --- | --- | --- | +| min | number | Lower bound of the dice roll | +| max | number | Upper bound of the dice roll | +| channel_name | string | Name of the chat channel | +| [channel_type] | DOTAChatChannelType_t | The type of the channel being joined | -#### sendMessage(channel, message, [channel_type]) -* `channel` - A string for the channel name. -* `message` - The message you want to send. -* `[channel_type]` - The type of the channel you want to send a message to. Use the `Dota2.schema.DOTAChatChannelType_t` enum. + -Sends a message to the specified chat channel. Won't send if you're not in the channel you try to send to. -If you've joined different channels with the same name, specify the type to prevent unexpected behaviour. +#### dota2Client.requestChatChannels() +Requests a list of chat channels from the GC. Listen for the `chatChannelsData` event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### flipCoin(channel, [channel_type]) -* `channel` - A string for the channel name. -* `[channel_type]` - The type of the channel you want to flip a coin in. Use the `Dota2.schema.DOTAChatChannelType_t` enum. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + -Sends a coin flip to the specified chat channel. Won't send if you're not in the channel you try to send to. -If you've joined different channels with the same name, specify the type to prevent unexpected behaviour. +#### dota2Client.requestPlayerMatchHistory(account_id, [options], [callback]) +Requests the given player's match history. The responses are paginated, +but you can use the `start_at_match_id` and `matches_requested` options to loop through them. +Provide a callback or listen for the [playerMatchHistoryData](#module_Dota2.Dota2Client+event_playerMatchHistoryData) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### rollDice(channel, min, max, [channel_type]) -* `channel` - A string for the channel name. -* `min` - Lower bound of the dice roll. -* `max` - Upper bound of the dice roll. -* `[channel_type]` - The type of the channel you want to roll a dice in. Use the `Dota2.schema.DOTAChatChannelType_t` enum. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Sends a dice roll to the specified chat channel. Won't send if you're not in the channel you try to send to. -If you've joined different channels with the same name, specify the type to prevent unexpected behaviour. +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| account_id | number | | Dota 2 account ID of the player whose match history the bot should fetch | +| [options] | Object | | Filtering options | +| [options.start_at_match_id] | number | | Which match ID to start searching at (pagination) | +| [options.matches_requested] | number | | How many matches to retrieve | +| [options.hero_id] | number | | Show only matches where player played the given hero | +| [options.request_id] | number | account_id | A unique identifier that identifies this request | +| [options.include_practice_matches] | boolean | | Whether or not to include practice matches in the results | +| [options.include_custom_games] | boolean | | Whether or not to include custom games in the results | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | | Called with `err, CMsgDOTAGetPlayerMatchHistoryResponse` | -#### requestChatChannels() + -Requests a list of chat channels from the GC. Listen for the `chatChannelsData` event for the GC's response. +#### dota2Client.requestProfileCard(account_id, [callback]) +Sends a message to the Game Coordinator requesting `account_id`'s profile card. +This method is heavily rate limited. When abused, the GC just stops responding. +Even the regular client runs into this limit when you check too many profiles. +Provide a callback or listen for [profileCardData](#module_Dota2.Dota2Client+event_profileCardData) event for Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -### Guild -#### requestGuildData() +| Param | Type | Description | +| --- | --- | --- | +| account_id | number | Dota 2 account ID of the player whose profile card the bot should fetch | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgDOTAProfileCard` | -Sends a request to the GC for new guild data, which returns `guildOpenPartyData` events - telling the client the status of current open parties for each guild, as well as exposing `guildIds` to the client. + +#### dota2Client.requestHallOfFame(week, [callback]) +Sends a message to the Game Coordinator requesting the Hall of Fame data for `week`. +Provide a callback or listen for the [hallOfFameData](#module_Dota2.Dota2Client+event_hallOfFameData) event for the Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### inviteToGuild(guild_id, target_account_id, [callback]) -* `guild_id` - ID of a guild. -* `target_account_id` - Account ID (lower 32-bits of a 64-bit steam id) of user to invite to guild. -* `[callback]` - optional callback, returns args: `err, response`. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Attempts to invite a user to guild. Requires the GC to be ready (listen for the `ready` event before calling). +| Param | Type | Description | +| --- | --- | --- | +| week | number | The week of which you wish to know the Hall of Fame members; will return latest week if omitted. Weeks are counted from start of unix epoch with a lower bound of 2233 (2012-10-18) | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgDOTAHallOfFameResponse` | -#### cancelInviteToGuild(guild_id, target_account_id, [callback]) -* `guild_id` - ID of a guild. -* `target_account_id` - Account ID (lower 32-bits of a 64-bit steam id) of user whoms guild invite you wish to cancel. -* `[callback]` - optional callback, returns args: `err, response`. + -Attempts to cancel a user's guild invitation; use this on your own account ID to reject guild invitations. Requires the GC to be ready (listen for the `ready` event before calling). +#### dota2Client.requestPlayerInfo(account_ids) +Sends a message to the Game Coordinator requesting one or multiple `account_ids` player information. +This includes their display name, country code, team info and sponsor, fantasy role, official information lock status, and if the user is marked as a pro player. +Listen for the [playerInfoData](#module_Dota2.Dota2Client+event_playerInfoData) event for the Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### setGuildAccountRole(guild_id, target_account_id, target_role, [callback]) -* `guild_id` - ID of a guild. -* `target_account_id` - Account ID (lower 32-bits of a 64-bit steam id) of user whoms guild invite you wish to cancel. -* `target_role` - Role in guild to have. - * `0` - Kick member from guild. - * `1` - Leader. - * `2` - Officer. - * `3` - Member. -* `[callback]` - optional callback, returns args: `err, response`. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Attempts to set a user's role within a guild; use this with your own account ID and the 'Member' role to accept guild invitations. Requires the GC to be ready (listen for the `ready` event before calling). +| Param | Type | Description | +| --- | --- | --- | +| account_ids | number | Array.<number> | Either a single or array of Account IDs (lower 32-bits of a 64-bit Steam ID) of desired user(s) player info. | -### Team -#### requestMyTeams([callback]) -* `[callback]` - optional callback, returns args: `err, response`. + -Requests the authenticated user's team data. +#### dota2Client.requestTrophyList(account_id, [callback]) +Sends a message to the Game Coordinator requesting `account_id`'s trophy data. +Provide a callback or listen for [trophyListData](#module_Dota2.Dota2Client+event_trophyListData) event for Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### requestTeamProfile(team_id, [callback]) - DEPRECATED -* `team_id` - ID of a team -* `[callback]` - optional callback, returns args: `err, response`. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Requests the profile for a given team. +| Param | Type | Description | +| --- | --- | --- | +| account_id | number | Dota 2 account ID of the player whose trophy data the bot should fetch | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgClientToGCGetTrophyListResponse` | -**Warning** protobuf no longer exists, function is now deprecated. + -#### requestTeamMemberProfile(steam_id, [callback]) - DEPRECATED -* `steam_id` - Steam ID of the user whose team profile you want -* `[callback]` - optional callback, returns args: `err, response`. +#### dota2Client.requestPlayerStats(account_id, [callback]) +Sends a message to the Game Coordinator requesting `account_id`'s player stats. +Provide a callback or listen for [playerStatsData](#module_Dota2.Dota2Client+event_playerStatsData) event for Game Coordinator's response. +This data contains all stats shown on a player's profile page. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Requests the profile of the team a given user belongs to. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -**Warning** protobuf no longer exists, function is now deprecated. +| Param | Type | Description | +| --- | --- | --- | +| account_id | number | Dota 2 account ID of the player whose player stats the bot should fetch | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgGCToClientPlayerStatsResponse` | -#### requestTeamIDByName(team_name, [callback]) - DEPRECATED -* `team_name` - Name of a team -* `[callback]` - optional callback, returns args: `err, response`. + -Requests the ID for a given team name. +#### dota2Client.requestJoinableCustomGameModes([server_region]) +Requests a list of custom game modes for which there are currently lobbies available. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -**Warning** protobuf no longer exists, function is now deprecated. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -#### requestProTeamList([callback]) - STATUS UNKNOWN -* `[callback]` - optional callback, returns args: `err, response`. +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [server_region] | ServerRegion | ServerRegion.UNSPECIFIED | The server region for which you'd like to obtain the joinable custom game modes | -Requests the list of pro teams. + -**Warning** this request no longer triggers a response from the GC. This might be temporary. +#### dota2Client.requestPlayerCardsByPlayer() ⇒ Array.<FantasyPlayer> +Requests the player stats for each of the players for which you have one or multiple player cards. +All requests are staggered in 200ms intervals and time out after 2s. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -### Community -#### requestPlayerMatchHistory(account_id, [options], [callback]) -* `account_id` - Account ID of the user whose match history you wish to retrieve. -* `[options]` - A mapping of options for the query he results: - * `[start_at_match_id]` - Which match ID to start searching at (pagination) - * `[matches_requested]` - How many matches to retrieve - * `[hero_id]` - The ID of the hero the given account ID had played - * `[request_id]` - I have no idea. - * `[include_practice_matches]` - Do you want practice matches in the result sets? - * `[include_custom_games]` - Do you want custom games in the result sets? -* `[callback]` - optional callback, returns args: `err, response`. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) +**Async**: Returns a list of promises that resolve to [FantasyPlayer](#module_Dota2.Dota2Client+requestPlayerCardsByPlayer.FantasyPlayer) objects + -Requests the given player's match history. The responses are paginated, but you can use the `start_at_match_id` and `matches_requested` options to loop through them. +##### requestPlayerCardsByPlayer.FantasyPlayer : Object +Player with player cards -Provide a callback or listen for the `playerMatchHistoryData` for the GC's response. Requires the GC to be ready (listen for the `ready` event before calling). +**Kind**: static typedef of [requestPlayerCardsByPlayer](#module_Dota2.Dota2Client+requestPlayerCardsByPlayer) +**Properties** -#### requestProfile(account_id, request_name, [callback]) - DEPRECATED -* `account_id` - Account ID (lower 32-bits of a 64-bit Steam ID) of the user whose profile data you wish to view. -* `request_name` - Boolean, whether you want the GC to return the accounts current display name. -* `[callback]` - optional callback, returns args: `err, response`. +| Name | Type | Description | +| --- | --- | --- | +| account_id | number | Dota2 account ID of the player | +| cards | Array.<Object> | Player cards of this player in the bot's inventory | +| cards[].id | number | ID of the card | +| cards[].bonuses | [Long](#external_Long) | 64bit bitmask for the bonuses of this card | +| stats | [CMsgGCToClientPlayerStatsResponse](#module_Dota2.schema.CMsgGCToClientPlayerStatsResponse) | Player stats | -Sends a message to the Game Coordinator requesting `account_id`'s profile data. Provide a callback or listen for `profileData` event for Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). + -**Warning** Valve's privacy policy has become stricter since reborn. This function is now reserved for internal use. +#### dota2Client.requestPlayerCardRoster(league_id, timestamp, [callback]) +Sends a message to the Game Coordinator requesting your fantasy line-up for a specific day of a given tournament. +Provide a callback or listen for the [playerCardRoster](#module_Dota2.Dota2Client+event_playerCardRoster) event for the Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### requestProfileCard (account_id, [callback]) -* `account_id` - Account ID (lower 32-bits of a 64-bit Steam ID) of the user whose profile card you wish to view. -* `[callback]` - optional callback, returns args: `err, response`. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Sends a message to the Game Coordinator requesting `account_id`'s profile card. Provide a callback or listen for `profileCardData` event for Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). +| Param | Type | Description | +| --- | --- | --- | +| league_id | number | ID of the league | +| timestamp | number | Date in timeframe of the league | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgClientToGCGetPlayerCardRosterResponse` | -#### requestPassportData(account_id, [callback]) - DEPRECATED -* `account_id` - Account ID (lower 32-bits of a 64-bit Steam ID) of the user whose passport data you wish to view. -* `[callback]` - optional callback, returns args: `err, response`. + -Sends a message to the Game Coordinator requesting `account_id`'s passport data. Provide a callback or listen for `passportData` event for Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). -This function is no longer supported by Valve, it's only left here for historical purposes. It will be removed in a future release. +#### dota2Client.draftPlayerCard(league_id, timestamp, slot, player_card_id, [callback]) +Sends a message to the Game Coordinator requesting to draft a certain player card in a specific slot, for a given day in a tournament. +Provide a callback or listen for the [playerCardDrafted](#module_Dota2.Dota2Client+event_playerCardDrafted) event for the Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### requestHallOfFame([week], [callback]) -* `[week]` - The week of which you wish to know the Hall of Fame members; will return latest week if omitted. Weeks also randomly start at 2233 for some reason, valf please. -* `[callback]` - optional callback, returns args: `err, response`. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Sends a message to the Game Coordinator requesting the Hall of Fame data for `week`. Provide a callback or listen for the `hallOfFameData` event for the Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). +| Param | Type | Description | +| --- | --- | --- | +| league_id | number | ID of the league for which you're drafting a player card | +| timestamp | number | Timestamp of the day for which you want to draft a player card | +| slot | number | Slot in the draft which you want to fill | +| player_card_id | number | Item ID of the player card you want to draft | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgClientToGCSetPlayerCardRosterResponse` | -#### requestPlayerInfo(account_ids) -* `account_ids` - Either a single or array of Account IDs (lower 32-bits of a 64-bit Steam ID) of desired user(s) player info. + -Sends a message to the Game Coordinator requesting one or multiple `account_ids` player information. This includes their display name, country code, team info and sponsor, fantasy role, official information lock status, and if the user is marked as a pro player. Listen for the `playerInfoData` event for the Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). +#### dota2Client.setItemPositions(item_positions) +Attempts to change the position of one or more items in your inventory. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### requestTrophyList(account_id, [callback]) -* `account_id` - Account ID (lower 32-bits of a 64-bit Steam ID) of the user whose trophy data you wish to view. -* `[callback]` - optional callback, returns args: `err, response`. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Sends a message to the Game Coordinator requesting `account_id`'s trophy data. Provide a callback or listen for `trophyListData` event for Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). Notably, this data contains the `profile_name` field, which is the user's name displayed on their profile page in dota. +| Param | Type | Description | +| --- | --- | --- | +| item_positions | Array.<Object> | The new positions of the items | +| item_positions[].item_id | number | ID of the item | +| item_positions[].position | number | New position of the item | -#### requestPlayerStats(account_id, [callback]) -* `account_id` - Account ID (lower 32-bits of a 64-bit Steam ID) of the user whose player stats you wish to view. -* `[callback]` - optional callback, returns args: `err, response`. -* -Sends a message to the Game Coordinator requesting `account_id`'s player stats. Provide a callback or listen for `playerStatsData` event for Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). This data contains all stats shown on a player's profile page. + +#### dota2Client.deleteItem(item_id) +Attempts to delete an item in your inventory. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -### Matches -#### requestMatches(criteria, [callback]) -* `[criteria]` - The options available for searching matches: - * `[hero_id]` - * `[game_mode]` - * `[date_min]` - * `[date_max]` - * `[matches_requested]` - * `[start_at_match_id]` - * `[min_players]` - * `[tournament_games_only]` - * `[account_id]` - * `[league_id]` - * `[skill]` - * `[team_id]` - -* `[callback]` - optional callback, returns args: `err, response`. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Requests matches from the GC matching the given criteria. Provide a callback or listen for the `matchesData` event for teh Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). +| Param | Type | Description | +| --- | --- | --- | +| item_id | number | ID of the item | -#### requestMatchDetails(match_id, [callback]) -* `match_id` - The match's ID -* `[callback]` - optional callback, returns args: `err, response`. + -Sends a message to the Game Coordinator requesting `match_id`'s match details. Provide a callback or listen for `matchDetailsData` event for Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). +#### dota2Client.requestLeaguesInMonth([month], [year], [tier], [callback]) +Sends a message to the Game Coordinator requesting data on leagues being played in the given month. +Provide a callback or listen for [leaguesInMonthData](#module_Dota2.Dota2Client+event_leaguesInMonthData) for the Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Note: There is a server-side rate-limit of 100 requests per 24 hours on this method. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -#### requestMatchMinimalDetails(match_ids, [callback]) - * `match_ids` - The match IDs that you want concise details of - * `[callback]` - optional callback, returns args: `err, response`. +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [month] | number | (new Date()).getMonth() | Month (MM) you want to query data for. **IMPORTANT NOTE**: Month is zero-aligned, not one-aligned; so Jan = 00, Feb = 01, etc. | +| [year] | number | (new Date()).getFullYear() | Year (YYYY) you want to query data for. | +| [tier] | number | 0 | Search only for a specific tier of tournaments. | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | | Called with `err, CMsgDOTALeaguesInMonthResponse` | -Sends a message to the Game Coordinator requesting the match details for matches corresponding to `match_ids`. Provide a callback or listen for `matchMinimalDetailsData` event for Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). + -#### requestMatchmakingStats() +#### dota2Client.requestLeagueInfo() +Requests info on all available official leagues from the GC. +Listen for the [leagueData](#module_Dota2.Dota2Client+event_leagueData) event for the Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Sends a message to the Game Coordinator requesting some matchmaking stats. Listen for the `matchmakingStatsData` event for the Game Coordinator's response (cannot take a callback because of Steam's backend, or RJackson's incompetence; not sure which). Requires the GC to be ready (listen for the `ready` event before calling). +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + -#### requestTopFriendMatches() +#### dota2Client.requestTopLeagueMatches() +Sends a message to the Game Coordinator requesting the top league matches. +Listen for the [topLeagueMatchesData](#module_Dota2.Dota2Client+event_topLeagueMatchesData) event for the Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Sends a message to the Game Coordinator requesting the top matches of your friends. Listen for the `topFriendMatchesData` event for the Game Coordinator's response (cannot take a callback because of Steam's backend). Requires the GC to be ready (listen for the `ready` event before calling). +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + +#### dota2Client.createPracticeLobby(options, [callback]) +Sends a message to the Game Coordinator requesting to create a lobby. +This will automatically make the bot join the first slot on radiant team. Listen for +[practiceLobbyUpdate](#module_Dota2.Dota2Client+event_practiceLobbyUpdate) response for a +snapshot-update of the newly created lobby. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -### Parties +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -### respondPartyInvite(id, accept, [ping_data]) -* `id` - Number, party ID. -* `accept` - Accept or decline the invite. -* `[ping_data]` - Optional argument to be provided when accepting a party invite. For contents see `CMsgClientPingData`. +| Param | Type | Description | +| --- | --- | --- | +| options | [Options](#module_Dota2.Dota2Client+Lobby.Options) | Configuration options for the lobby | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -Responds to an incoming party invite. The `PartyInvite` property is cleared after the response has been sent. + +#### ~~dota2Client._createPracticeLobby()~~ +***Deprecated*** -### inviteToParty(id) -* `[id]` - The steam ID to invite. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + -Invites a player to a party. This will create a new party if you aren't in one. +#### ~~dota2Client.createTournamentLobby()~~ +***Deprecated*** +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + -### kickFromParty(id) -* `[id]` - The steam ID to kick. +#### dota2Client.configPracticeLobby(lobby_id, options, [callback]) +Sends a message to the Game Coordinator requesting to configure some options of the active lobby. +Listen for [practiceLobbyUpdate](#module_Dota2.Dota2Client+event_practiceLobbyUpdate) response +for a snapshot-update of the newly created lobby. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Kicks a player from the party. This will create a new party if you aren't in one. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) +| Param | Type | Description | +| --- | --- | --- | +| lobby_id | [Long](#external_Long) | ID of the lobby | +| options | [Options](#module_Dota2.Dota2Client+Lobby.Options) | The new option values | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -### setPartyCoach(coach) -* `[coach]` - Boolean, if the bot wants to be coach or not. + -Set the bot's status as a coach. +#### dota2Client.requestPracticeLobbyList([callback]) +Requests a lists of joinable practice lobbies. +Provide a callback or listen for the [practiceLobbyListData](#module_Dota2.Dota2Client+event_practiceLobbyListData) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -### setPartyLeader(id) -* `[id]` - The steam ID of new party leader. +| Param | Type | Description | +| --- | --- | --- | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyListResponse` | -Set the new party leader. + +#### dota2Client.requestFriendPracticeLobbyList([callback]) +Requests a lists of joinable practice lobbies which have one of your friends in them. +Provide a callback or listen for the [friendPracticeLobbyListData](#module_Dota2.Dota2Client+event_friendPracticeLobbyListData) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -### leaveParty() +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Leaves the current party. See the `Party` property. +| Param | Type | Description | +| --- | --- | --- | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgFriendPracticeLobbyListResponse` | + -### Lobbies -### respondLobbyInvite(id, accept) -* `[id]` - Practice lobby ID -* `[accept]` - Boolean, whether or not you accept the invitation. +#### dota2Client.balancedShuffleLobby([callback]) +Shuffles the lobby based on skill level. Requires you to be in a lobby and to be the host. +Provide a callback or listen for the [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Sends a message to the Game Coordinator confirming a lobby invitation. The `LobbyInvite` property is cleared after the response is sent. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -### joinPracticeLobby(id, [password], [callback]) -* `[id]` - Practice lobby ID -* `[password]` - Practice lobby password -* `[callback]` - Optional callback, returns args: `err, response`. +| Param | Type | Description | +| --- | --- | --- | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -Sends a message to the Game Coordinator requesting to join a lobby. Provide a callback or listen for `practiceLobbyJoinResponse` for the Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). + -#### createPracticeLobby([password], [options], [callback]) -* `[password]` - Password to restrict access to the lobby (optional). -* `[options]` - Options available for the lobby. All are optional, but send at least one. - * `game_name`: String, lobby title. - * `server_region`: Use the ServerRegion enum. - * `game_mode`: Use the DOTA_GameMode enum. - * `game_version`: Use the game version enum. - * `cm_pick`: Use the DOTA_CM_PICK enum. - * `allow_cheats`: Boolean, allow cheats. - * `fill_with_bots`: Boolean, fill available slots with bots? - * `allow_spectating`: Boolean, allow spectating? - * `pass_key`: Password. - * `series_type`: Use the series type enum. - * `radiant_series_wins`: # of games won so far, e.g. for a Bo3 or Bo5. - * `dire_series_wins`: # of games won so far, e.g. for a Bo3 or Bo5. - * `allchat`: Enable all chat for VOIP - * `league_id`: The league this lobby is being created for. Optional - * `dota_tv_delay`: Number of seconds the game should be delayed for DotaTV. - * `custom_game_mode`: TODO. - * `custom_map_name`: TODO. - * `custom_difficulty`: TODO. - * `custom_game_id`: TODO. -* `[callback]` - optional callback, returns args: `err, response`. +#### dota2Client.flipLobbyTeams([callback]) +Flips the radiant and dire team players. Requires you to be in a lobby and to be the host. +Provide a callback or listen for the [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Sends a message to the Game Coordinator requesting to create a lobby. Listen for `practiceLobbyUpdate` response for a snapshot-update of the newly created lobby. Requires the GC to be ready (listen for the `ready` event before calling). +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -#### createTournamentLobby([password], [tournament_game_id], [tournament_id], [options], [callback]) -* `[password]` - See paramter description in [#createPracticeLobby] -* `[tournament_game_id]` - TODO -* `[tournament_id]` - TODO -* `[options]` - See paramter description in [#createPracticeLobby] -* `[callback]` - optional callback, returns args: `err, response`. +| Param | Type | Description | +| --- | --- | --- | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -Sends a message to the Game Coordinator requesting to create a tournament lobby. Listen for `practiceLobbyUpdate` response for a snapshot-update of the newly created lobby. Requires the GC to be ready (listen for the `ready` event before calling). + -#### joinPracticeLobbyTeam(slot, team, [callback]) -* `slot` - The slot you want to fill (1-10) -* `team` - The team you want to be on. Use the `GOTA_GC_TEAM` enum -* `[callback]` - optional callback, returns args: `err, response`. +#### dota2Client.inviteToLobby(steam_id) +Asks to invite a player to your lobby. This creates a new default lobby when you are not already in one. +Listen for the [inviteCreated](#module_Dota2.Dota2Client+event_inviteCreated) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Sends a message to the Game Coordinator requesting to join a particular team in the lobby. Provide a callback or listen for `practiceLobbyResponse` for the Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -#### addBotToPracticeLobby(slot, team, bot_difficulty, [callback]) -* `slot` - The slot you want to fill (1-10) -* `team` - The team you want to be on. Use the `DOTA_GC_TEAM` enum -* `bot_difficulty` - The difficulty setting of the bot. Use the `DOTABotDifficulty`enum -* `[callback]` - optional callback, returns args: `err, response`. +| Param | Type | Description | +| --- | --- | --- | +| steam_id | [Long](#external_Long) | The Steam ID of the player you want to invite. | -Sends a message to the Game Coordinator requesting to add a bot to the given team in the lobby. Provide a callback or listen for `practiceLobbyResponse` for the Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). + -#### joinPracticeLobbyBroadcastChannel(channel, [callback]) - * `channel` - The channel slot you want to fill (default: 1) - * `[callback]` - optional callback, returns args: `err, response`. +#### dota2Client.practiceLobbyKick(account_id, [callback]) +Asks to kick someone from your current practice lobby. Requires you to be in a lobby and to be the host. +Provide a callback or listen for the [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). - Sends a message to the Game Coordinator requesting to add a bot to the broadcast channel. Provide a callback or listen for `practiceLobbyResponse` for the Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -#### balancedShuffleLobby() +| Param | Type | Description | +| --- | --- | --- | +| account_id | number | The Dota2 account ID of the player you want to kick. | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -Shuffles the lobby teams. + -#### flipLobbyTeams() +#### dota2Client.practiceLobbyKickFromTeam(account_id, [callback]) +Asks to kick someone from his chosen team in your current practice lobby. +The player will be added to the player pool +Provide a callback or listen for the [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Flips the teams in a lobby. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -#### configPracticeLobby(lobby_id, options, [callback]) -* `lobby_id` - Lobby ID -* `options` - See paramter description in [#createPracticeLobby] -* `[callback]` - optional callback, returns args: `err, response`. +| Param | Type | Description | +| --- | --- | --- | +| account_id | number | The Dota2 account ID of the player you want to kick from his team. | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -Sends a message to the Game Coordinator requesting to configure some options of the active lobby. Requires the GC to be ready (listen for the `ready` event before calling). + -#### launchPracticeLobby() +#### dota2Client.joinPracticeLobby(id, password, [callback]) +Sends a message to the Game Coordinator requesting to join a lobby. +Provide a callback or listen for the [practiceLobbyJoinResponse](#module_Dota2.Dota2Client+event_practiceLobbyJoinResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Sends a message to the GC requesting the currrent lobby be started (server found and game begins). You will receive updates in the `practiceLobbyUpdate` response. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -#### inviteToLobby(steam_id) -* `steam_id` The Steam ID of the player you want to invite. +| Param | Type | Description | +| --- | --- | --- | +| id | externalLong | The ID of the lobby | +| password | number | The password of the lobby | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -Asks to invite a player to your lobby. This creates a new default lobby when you are not already in one. + -#### practiceLobbyKick(account_id, [callback]) -* `account_id` The ID of the player you want to kick. +#### dota2Client.leavePracticeLobby([callback]) +Sends a message to the Game Coordinator requesting to leave the current lobby. +Provide a callback or listen for the [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Asks to kick someone from your current practice lobby. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -#### practiceLobbyKickFromTeam(account_id, [callback]) -* `account_id` The ID of the player you want to kick from the team. +| Param | Type | Description | +| --- | --- | --- | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -Asks to kick someone from his chosen team in your current practice lobby. + -#### leavePracticeLobby() +#### dota2Client.abandonCurrentGame([callback]) +Abandons the current game. +Provide a callback or listen for the [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Sends a message to the Game Coordinator requesting to leave the current lobby. Requires the GC to be ready (listen for the `ready` event before calling). +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -#### requestPracticeLobbyList +| Param | Type | Description | +| --- | --- | --- | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -TODO + -#### requestFriendPractiseLobbyList +#### dota2Client.launchPracticeLobby([callback]) +Start the practice lobby. The bot will continue to receive lobby updates, but won't join the actual game. +Requires you to be in a lobby and to be the host. +Provide a callback or listen for the [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -TODO +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -### Custom games -#### requestJoinableCustomGameModes([server_region]) -* `[region]` - Enum for the server region, defaults to Dota2.ServerRegion.UNSPECIFIED +| Param | Type | Description | +| --- | --- | --- | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -Sends a message to the Game Coordinator requesting a list of joinable custom games for a given region. + -### Leagues -#### requestLeaguesInMonth([month], [year], [tier], [callback]) -* `[month]` - Int for the month (MM) you want to query data for. Defaults to current month. **IMPORTANT NOTE**: Month is zero-aligned, not one-aligned; so Jan = 00, Feb = 01, etc. -* `[year]` - Int for the year (YYYY) you want to query data for . Defaults to current year. -* `[tier]` - Search only for a specific tier of tournaments. Defaults to 0. -* `[callback]` - optional callback` returns args: `err` response`. +#### dota2Client.joinPracticeLobbyTeam(slot, team, [callback]) +Sends a message to the Game Coordinator requesting to join a particular team in the lobby. +Requires you to be in a lobby. +Provide a callback or listen for the [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Sends a message to the Game Coordinator requesting data on leagues being played in the given month. Provide a callback or listen for `leaguesInMonthData` for the Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -#### requestLeagueInfo() +| Param | Type | Description | +| --- | --- | --- | +| slot | number | The slot you want to join | +| team | number | The team you want to join | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -Requests info on all available official leagues from the GC. Listen for `leagueData` for the Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). + -#### requestTopLeagueMatches() +#### dota2Client.joinPracticeLobbyBroadcastChannel([channel], [callback]) +Sends a message to the Game Coordinator requesting to add a bot to the broadcast channel. +Requires you to be in a lobby. +Provide a callback or listen for the [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -Sends a message to the Game Coordinator requesting the top league matches. Listen for the `topLeagueMatchesData` event for the Game Coordinator's response (cannot take a callback because of Steam's backend). Requires the GC to be ready (listen for the `ready` event before calling). +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -### Fantasy -#### requestPlayerCardRoster(league_id, timestamp, [callback]) -* `league_id` - ID of the league for which you're requesting your player card roster -* `timestamp` - timestamp of the day for which you want your player card roster -* `[callback]` - optional callback` returns args: `err` response`. - -Sends a message to the Game Coordinator requesting your fantasy line-up for a specific day of a given tournament. Listen for the `playerCardRoster` event for the Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [channel] | number | 1 | The channel slot you want to fill | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | | Called with `err, CMsgPracticeLobbyJoinResponse` | -#### draftPlayerCard(league_id, timestamp, slot, player_card_id, [callback]) -* `league_id` - ID of the league for which you're drafting a player card -* `timestamp` - timestamp of the day for which you want to draft a player card -* `slot` - Slot in the draft which you want to fill -* `player_card_id` - Item ID of the player card you want to draft -* `[callback]` - optional callback` returns args: `err` response`. + -Sends a message to the Game Coordinator requesting to draft a certain player card in a specific slot, for a given day in a tournament. Listen for the `playerCardDrafted` event for the Game Coordinator's response. Requires the GC to be ready (listen for the `ready` event before calling). -### SourceTV +#### dota2Client.addBotToPracticeLobby(slot, team, bot_difficulty, [callback]) +Sends a message to the Game Coordinator requesting to add a bot to the given team in the lobby. +Requires you to be in a lobby and to be the host +Provide a callback or listen for the [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -#### requestSourceTVGames([filterOption]) +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -* `[filterOption]` - Object to override the default filters +| Param | Type | Description | +| --- | --- | --- | +| slot | number | The slot you want to add a bot to | +| team | number | The team you want to add a bot to | +| bot_difficulty | [BotDifficulty](#module_Dota2.BotDifficulty) | The difficulty setting of the bot. | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgPracticeLobbyJoinResponse` | -Returns a list of current ongoing matches (from live games tab). + -Default filterOptions: +#### dota2Client.respondLobbyInvite(id, accept) +Sends a message to the Game Coordinator confirming/denying a lobby invitation +Provide a callback or listen for the [practiceLobbyResponse](#module_Dota2.Dota2Client+event_practiceLobbyResponse) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -```javascript -{ - search_key: '', - league_id: 0, - hero_id: 0, - start_game: 0, // This is not the game offset, only values in [0, 10, 20, ... 90] are valid, and yield [1,2,3 ... 10] responses - game_list_index: 0, - lobby_ids: [], // This is for getting player specific matches (pro player) games on the live games list, but where the lobby_ids are derived from is unknown. -} -``` +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -> __Important:__ The useful parameters are `league_id`, `hero_id`, and `start_game`. The rest have unclear usage conditions. - -## Events -### `ready` -Emitted when the GC is ready to receive messages. Be careful not to declare anonymous functions as event handlers here, as you'll need to be able to invalidate event handlers on an `unready` event. - -### `unready` -Emitted when the connection status to the GC changes, and renders the library unavailable to interact. You should clear any event handlers set in the `ready` event here, otherwise you'll have multiple handlers for each message every time a new `ready` event is sent. - -### `popup` (`type`, `popup`) -* `type` - The type of the popup. See `CMsgDOTAPopup.PopupID` -* `popup` - The raw popup data - -Generic popup, can be produced for a plethora of reasons. - -### `chatMessage` (`channel`, `senderName`, `message`, `chatObject`) -* `channel` - Channel name. -* `senderName` - Persona name of user who sent message. -* `message` - Wot u think? -* `chatObject` - The raw chat object to do with as you wish. - -Emitted for chat messages received from Dota 2 chat channels - -### `chatJoin` (`channel`, `joiner_name`, `joiner_steam_id`, `otherJoined_object`) -* `channel` - Channel name. -* `joiner_name` - Persona name of user who joined. -* `joiner_steam_id` - Steam ID of the user who joined. -* `otherJoined_object` - The raw `CMsgDOTAOtherJoinedChatChannel` object for you to do with as you wish. - -Emitted when another user joins a chat channel you are in. - -### `chatLeave` (`channel`, `leaver_steam_id`, `otherLeft_object`) -* `channel` - Channel name. -* `leaver_steam_id` - Steam ID of the user who left. -* `otherLeft_object` - The raw `CMsgDOTAOtherLeftChatChannel` object for you to do with as you wish. - -Emitted when another user leaves a chat channel you are in. +| Param | Type | Description | +| --- | --- | --- | +| id | [Long](#external_Long) | The ID of the lobby | +| accept | boolean | Whether or not you accept the invitation. | -### `chatChannelsData` (`channels`) -* `channels` - An array of ChatChannel objects, each with the following properties: - * `channel_name` - * `num_members` - * `channel_type` + -The GC's response to a requestChatChannels call. +#### dota2Client.requestMatches([criteria], [callback]) +Requests a list of matches corresponding to the given criteria. The responses are paginated, +but you can use the `start_at_match_id` and `matches_requested` options to loop through them. +Provide a callback or listen for the [matchesData](#module_Dota2.Dota2Client+event_matchesData) event for the GC's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -### `guildOpenPartyData` (`guild_id`, `openParties`) -* `guild_id` - ID of the guild. -* `openParties` - Array containing information about open guild parties. Each object has the following properties: - * `partyId` - Unique ID of the party. - * `member_account_ids` - Array of account ids. - * `time_created` - Something about Back to the Future. - * `description` - A user-inputted string. Do not trust. - -Emitted for each guild the bot's account is a member of, containing information on open parties for each guild. Also exposes guild_id's, which is handy. - -### `guildData` (`guild_id`, `members`, `guildDataObject`) -* `guild_id` - ID of the guild. -* `members` - A list of members in the guild. Each object has the following properties: - * `account_id` - Account ID of the member. - * `time_joined` - Timestamp of when this user joined the guild. - * `role` - Role of the member withing the guild - * `1` - Leader - * `2` - Officer - * `3` - Member -* `guildDataObject` - The raw `CMsgDOTAGuildSDO` object. - -Emitted when information on a particular guild is retrieved. - -### `guildInviteData` (`guild_id`, `guildName`, `inviter`, `guildInviteDataObject`) -* `guild_id` - ID of the guild. -* `guildName` - Name of the guild. -* `inviter` - Account ID of user whom invited you. -* `guildInviteDataObject` - The raw guildInviteData object to do with as you wish. - -You can respond with `cancelInviteToGuild` or `setGuildAccountRole`. - -### `teamData` (`teams`, `league_id`) -* `teams` - Array containing the teams the user is in or which are featured on the user's profile. Each object has the following properties: - * `on_team` - Whether or not the user is on this team - * `profile_team` - Whether or not this is a team featured on the user's profile - * `team` - Info about the team. This contains among others: - * `name` - Name of the team - * `members` - Account ID and time joined for all members - * `wins` - All wins - * `losses` - All losses - * `gamesplayed` - Total amount of games played - * `rank` - Team MMR - * ... -* `league_id` - League ID (no clue as of its meaning, feel free to suggest) - -Emitted when GC responds to the `requestMyTeams` method. - -See the [protobuf schema](https://github.com/SteamRE/SteamKit/blob/master/Resources/Protobufs/dota/dota_gcmessages_client.proto#L776) for `team`'s object structure. - -### `teamProfile` (`team_id`, `team_info`) - DEPRECATED -* `team_id` - ID of the team. -* `team_info` - Info about the team. This contains among others: - * `name` - Name of the team - * `members` - Account ID and time joined for all members - * `wins` - All wins - * `losses` - All losses - * `gamesplayed` - Total amount of games played - * `rank` - Team MMR - * ... - -Emitted when GC responds to the `requestTeamProfile` and `requestTeamMemberProfile` method. - -See the [protobuf schema](https://github.com/SteamRE/SteamKit/blob/master/Resources/Protobufs/dota/dota_gcmessages_client.proto#L776) for `team_info`'s object structure. - -### `teamID` (`team_id`) - DEPRECATED -* `team_id` - ID of the team. Null if none was found. - -Emitted when GC responds to the `requestTeamIDByName` method. - -### `proTeamListData` (`teams`) -* `teams` - List of team entries - * `team_id` - ID of the team - * `tag` - Tag of the team - * `time_created` - Timestamp when the team was created - * `logo` - Logo of the team - * `country_code` - 2 letter country code - * `member_count`- Number of team members in this team - -Emitted when GC responds to the `requestProTeamList` method. - -### `profileData` (`account_id`, `profileData`) - DEPRECATED -* `account_id` - Account ID whom the data is associated with. -* `profileData` - The raw profile data object. - -Emitted when GC responds to the `requestProfile` method. - -See the [protobuf schema](https://github.com/SteamRE/SteamKit/blob/master/Resources/Protobufs/dota/dota_gcmessages_common.proto#L1584) for `profileData`'s object structure. - -### `profileCardData` (`account_id`, `profileCardData`) -* `account_id` - Account ID whom the data is associated with. -* `profileCardData` - The raw profileCard object. - -Emitted when GC responds to the `requestProfileCard` method. - -See the [protobuf schema](https://github.com/SteamRE/SteamKit/blob/master/Resources/Protobufs/dota/dota_gcmessages_common.proto#L1584) for `profileCardData`'s object structure. - -### `playerInfoData` (`playerInfoResponse`) -* `playerInfoResponse` - The raw playerInfo object. - * `leaderboards` - Empty array, details unknown. - * `player_infos` - List of player information - * `account_id` - The Account ID of the requested user. - * `name` - The display name for the user. - * `country_code` - The abbreviated country code for the user, i.e. `us`, `cn`, etc... - * `fantasy_role` - The role of the player, either core or support, `1` and `2` respectively. - * `team_id` - The numerical id of the user's team. - * `team_name` - The name of the team the user is on, ex: `Cloud9` - * `team_tag` - The abbreviated tag of a team prepended to a player's name, ex: `C9` - * `sponsor` - The sponsor listed in the player's official info, ex: `HyperX` - * `is_locked` - Whether or not the user's official player info has been locked from editing, `true` or `false`. - * `is_pro` - Whether the player is considered a pro player by Valve, `true` or `false`. - -Emitted when GC responds to the `requestPlayerInfo` method. - -See the [protobuf schema](https://github.com/SteamRE/SteamKit/blob/master/Resources/Protobufs/dota/dota_gcmessages_client_fantasy.proto#L159) for `playerInfoData`'s object structure. - -### `trophyListData` (`trophyListResponse`) -* `trophyListResponse` - The raw trophyListResponse object. - * `profile_name` - The name displayed on the user's dota profile page and profile card. - * `trophies` - List of trophies owned by the user. The following values are all integers. - * `trophy_id` - Id of the trophy. - * `trophy_score` - The score this trophy has counted. This is usually a level, but can represent other things, like number of challenges completed, or coins collected, etc... - * `last_updated` - The last time the trophy has been updated, in Unix time. - -Emitted when GC responds to the `requestTrophyList` method. - -### `playerMatchHistoryData` (`request_id`, `matchHistoryResponse`) - -TODO - -### `passportData` (`account_id`, `passportData`) - DEPRECATED -* `account_id` - Account ID whom the passport belongs to. -* `passportData` - The raw passport data object. - -Emitted when GC responds to the `requestPassportData` method. - -See the [protobuf schema](https://github.com/SteamRE/SteamKit/blob/master/Resources/Protobufs/dota/dota_gcmessages_client_fantasy.proto#L961) for `passportData`'s object structure. - -### `playerStatsData` (`account_id`, `playerStats`) -* `account_id` - Account ID whom the stats belong to. -* `playerStats` - Statistics about the player. This entails: - * `account_id` - * `player_stats` - * `match_count` - * `mean_gpm` - * `mean_xppm` - * `mean_lasthits` - * `rampages` - * `triple_kills` - * `first_blood_claimed` - * `first_blood_given` - * `couriers_killed` - * `aegises_snatched` - * `cheeses_eaten` - * `creeps_stacked` - * `fight_score` - * `farm_score` - * `support_score` - * `push_score` - * `versatility_score` +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -Emitted when the GC responds to the `requestPlayerStats` method. +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [criteria] | Object | | Filtering options | +| [criteria.hero_id] | number | | Show only matches where someone played the given hero | +| [criteria.game_mode] | number | | Game mode | +| [criteria.start_at_match_id] | number | | Which match ID to start searching at (pagination) | +| [criteria.matches_requested] | number | 1 | How many matches to retrieve | +| [criteria.min_players] | number | | Minimum number of players present during the match | +| [criteria.request_id] | number | | A unique identifier that identifies this request | +| [criteria.tournament_games_only] | boolean | | Whether or not to only include tournament games | +| [criteria.account_id] | number | | Dota2 account ID of a player that needs to be present in all matches | +| [criteria.league_id] | number | | Show only matches from the league with this ID | +| [criteria.skill] | number | | Skill level of the matches. 0 = Any, 3 = Very high skill. | +| [criteria.team_id] | number | | Team ID of the team that's played in the matches | +| [criteria.custom_game_id] | number | | Show only custom games with the given ID | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | | Called with `err, CMsgDOTARequestMatchesResponse` | -### `hallOfFameData` (`week`, `featuredPlayers`, `featuredFarmer`, `hallOfFameResponse`) -* `week` - Week the data is associated with. -* `featuredPlayers` - Array of featured players for that week. `[{ account_id, heroId, averageScaledMetric, numGames }]` -* `featuredFarmer` - Featured farmer for that week. `{ account_id, heroId, goldPerMin, match_id }` -* `hallOfFameResponse` - Raw response object. + -Emitted when the GC responds to the `requestHallOfFame` method. +#### dota2Client.requestMatchDetails(match_ids, [callback]) +Sends a message to the Game Coordinator requesting the match details for the given match ID. +This method is rate limited. When abused, the GC just stops responding. +Provide a callback or listen for [matchDetailsData](#module_Dota2.Dota2Client+event_matchDetailsData) event for Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -### `matchesData` +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -TODO +| Param | Type | Description | +| --- | --- | --- | +| match_ids | Array.<number> | List of match ID's for which the bot should fetch the details | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgGCMatchDetailsResponse` | -### `matchDetailsData` (`match_id`, `matchDetailsData`) -* `match_id` - Match ID whom the data is associatd with. -* `matchDetailsData` - The raw match details data object. + -Emitted when GC responds to the `requestmatchDetails` method. +#### dota2Client.requestMatchMinimalDetails(match_id, [callback]) +Sends a message to the Game Coordinator requesting the minimal match details for the given match ID. +This method is rate limited. When abused, the GC just stops responding. +Provide a callback or listen for [matchMinimalDetailsData](#module_Dota2.Dota2Client+event_matchMinimalDetailsData) event for Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -See the [protobuf schema](https://github.com/SteamRE/SteamKit/blob/master/Resources/Protobufs/dota/dota_gcmessages_client.proto#L1571) for `matchDetailsData`'s object structure. +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) -### `matchMinimalDetailsData` (`matchMinimalDetailsData`) -* `last_match` - Bool, usage unknown -* `matchMinimalDetailsData` - The raw match details data object. +| Param | Type | Description | +| --- | --- | --- | +| match_id | number | Match ID for which the bot should fetch the minimal details | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgClientToGCMatchesMinimalResponse` | -Emitted when GC responds to the `requestMatchMinimalDetails` method. + -See the [protobuf schema](https://github.com/SteamRE/SteamKit/blob/5acc8bb72bb7fb79ad08723a431fcbfe90669230/Resources/Protobufs/dota/dota_gcmessages_client.proto#L621-L650) for `matchMinimalDetailsData`'s object structure. +#### dota2Client.requestMatchmakingStats() +Sends a message to the Game Coordinator requesting the current match making stats. +Listen for [matchmakingStatsData](#module_Dota2.Dota2Client+event_matchmakingStatsData) event for Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -### `matchmakingStatsData` (`matchgroups_version`, `match_groups`, `matchmakingStatsResponse`) -* `matchgroups_version` - Version of the current list of match groups. -* `match_groups` - Array of CMsgMatchmakingMatchGroupInfo objects. Contains info on the number of people searching and ping penalty. -* `matchmakingStatsResponse` - Raw response object. - -Emitted when te GC response to the `requestMatchmakingStats` method. The array order dictates which matchmaking groups the figure belongs to. -The groups are discoverable through [regions.txt](https://github.com/SteamDatabase/GameTracking/blob/master/dota/game/dota/pak01_dir/scripts/regions.txt) in Dota 2's game files. We maintain an indicative list *without guarantees* in this README. -This list is manually updated only when changes are detected by community members, so it can be out of date. -Here are the groups at the time of this sentence being written (with unecessary data trimmed out): +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + -``` - "USWest": {"matchgroup": "0"}, - "USEast": {"matchgroup": "1"}, - "Europe": {"matchgroup": "2"}, - "Singapore": {"matchgroup": "3"}, - "Shanghai": {"matchgroup": "4"}, - "Brazil": {"matchgroup": "5"}, - "Korea": {"matchgroup": "6"}, - "Stockholm": {"matchgroup": "7"}, - "Austria": {"matchgroup": "8"}, - "Australia": {"matchgroup": "9"}, - "SouthAfrica": {"matchgroup": "10"}, - "PerfectWorldTelecom": {"matchgroup": "11"}, - "PerfectWorldUnicom": {"matchgroup": "12"}, - "Dubai": {"matchgroup": "13"}, - "Chile": {"matchgroup": "14"}, - "Peru": {"matchgroup": "15"}, - "India": {"matchgroup": "16"}, - "PerfectWorldTelecomGuangdong": {"matchgroup": "17"}, - "PerfectWorldTelecomZhejiang": {"matchgroup": "18"}, - "Japan": {"matchgroup": "19"}, - "PerfectWorldTelecomWuhan": {"matchgroup": "20"} -``` +#### dota2Client.requestTopFriendMatches() +Sends a message to the Game Coordinator requesting the current top matches played by your friends. +Listen for [topFriendMatchesData](#module_Dota2.Dota2Client+event_topFriendMatchesData) event for Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). + +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + + +#### dota2Client.respondPartyInvite(id, [accept], [ping_data]) +Responds to a party invite. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). + +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| id | [Long](#external_Long) | | The party's ID | +| [accept] | boolean | false | Whether or not you accept the invite | +| [ping_data] | CMsgClientPingData | | Optional argument that can be provided when accepting an invite. Contains a.o. the ping to the different servers. | + + + +#### dota2Client.leaveParty() +Leaves the current party. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). + +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + + +#### dota2Client.setPartyLeader(steam_id) +Tries to assign a party member as party leader. +Only works if you are a party leader and the proposed user is a member of +the current party. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). + +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| steam_id | [Long](#external_Long) | The Steam ID of the new party leader | + + + +#### dota2Client.setPartyCoach(coach) +Announces whether or not you want to be coach of the current party. GC will take action accordingly. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). + +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| coach | boolean | True if you want to be coach, false if you no longer want to be coach | + + + +#### dota2Client.inviteToParty(steam_id) +Invite a player to your party. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). + +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| steam_id | [Long](#external_Long) | Steam ID of the player you want to invite | -### `topFriendMatchesData` (`matches`) -* `matches` - A list of matches. Each match contains: - * `match_id` - Match ID - * `start_time` - Unix time of the start of the match - * `duration` - Duration of the match in seconds - * `game_mode` - Game mode - * `winning_team` - Team who won the match - * `players` - List of all the players in the game, contains id, hero, K/D/A and items - * `league` - Information on the league if this is a league match + -Emitted when the GC responds to the `requestTopFriendMatches` method. +#### dota2Client.kickFromParty(steam_id) +Kick a player from your party. Only works if you're party leader. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). -### `practiceLobbyUpdate` (`lobby`) -* `lobby` - The full lobby object (see `CSODOTALobby`). +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) +| Param | Type | Description | +| --- | --- | --- | +| steam_id | [Long](#external_Long) | Steam ID of the player you want to kick | + + + +#### dota2Client.requestSourceTVGames(filter_options) +Requests a list of SourceTV games based on the given criteria. +Listen for [sourceTVGamesData](#module_Dota2.Dota2Client+event_sourceTVGamesData) for results +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). + +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| filter_options | CSourceTVGameSmall | Filter options. Check the protobuf for a full list. | +| filter_options.league_id | number | ID of a league | +| filter_options.hero_id | number | ID of a hero that must be present in the game | +| filter_options.start_game | number | Number of pages sent, only values in [0, 10, 20, ... 90] are valid, and yield [1,2,3 ... 10] responses | + + + +#### dota2Client.requestMyTeams([callback]) +Sends a message to the Game Coordinator requesting the authenticated user's team data. +Provide a callback or listen for [teamData](#module_Dota2.Dota2Client+event_teamData) for the Game Coordinator's response. +Requires the GC to be [ready](#module_Dota2.Dota2Client+event_ready). + +**Kind**: instance method of [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| [callback] | [requestCallback](#module_Dota2..requestCallback) | Called with `err, CMsgDOTATeamsInfo` | + + + +#### "ready" +Emitted when the connection with the GC has been established +and the client is ready to take requests. + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + + +#### "unhandled" (kMsg, kMsg_name) +Emitted when the GC sends a message that isn't yet treated by the library. + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| kMsg | number | Proto message type ID | +| kMsg_name | string | Proto message type name | + + + +#### "hellotimeout" +Emitted when the connection with the GC takes longer than 30s + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + + +#### "inventoryUpdate" (inventory) +Emitted when the GC sends an inventory snapshot. The GC is incredibly +inefficient and will send the entire object even if it's a minor update. +You can use this to detect when a change was made to your inventory (e.g. drop) +Note that the [Inventory](#module_Dota2.Dota2Client+Inventory) property will be the old value until after this event +completes to allow comparison between the two. + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| inventory | Array.<CSOEconItem> | A list of `CSOEconItem` objects | + + + +#### "practiceLobbyUpdate" (lobby) Emitted when the GC sends a lobby snapshot. The GC is incredibly inefficient and will send the entire object even if it's a minor update. You can use this to detect when a lobby has been entered / created -successfully as well. Note that the `Lobby` property will be the old +successfully as well. Note that the [Lobby](#module_Dota2.Dota2Client+Lobby) property will be the old value until after this event completes to allow comparison between the two. -### `lobbyInviteCleared` () - -Emitted when the Lobby Invite is cleared, for example when -accepting/rejecting it or when the lobby is closed. - -### `practiceLobbyJoinResponse`(`result`, `practiceLobbyJoinResponse`) -* `result` - The result object from `practiceLobbyJoinResponse`. -* `practiceLobbyJoinResponse` - The raw response object. +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) -Emitted when the GC responds to `joinPracticeLobby` method. +| Param | Type | Description | +| --- | --- | --- | +| lobby | CSODOTALobby | The new state of the lobby. | -### `practiceLobbyCleared` () + +#### "practiceLobbyCleared" Emitted when leaving a lobby (aka, the lobby is cleared). This can -happen when kicked, upon leaving a lobby, etc. There are other callbacks +happen when kicked, upon leaving a lobby, etc. There are other events to tell when the bot has been kicked. -### `practiceLobbyResponse` (`result`, `practiceLobbyResponse`) -* `result` - The result object from `practiceLobbyJoinResponse`. -* `practiceLobbyResponse` - The raw response object. - -Emitted when an operation changing the state of a lobby was sent to the GC and -processed. This event only contains the acknowledgement by the GC. The actual -update of the lobby state is communicated via `practiceLobbyUpdate` events. - -### `friendPracticeLobbyListData` () - -TODO +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + -### `joinableCustomGameModes` (`game_modes`) -* `game_modes` - List of custom game modes that are available in a given server region - * `custom_game_id` - ID corresponding to a custom game mode - * `lobby_count` - Number of lobbies available for the game mode - * `player_count` - Number of players playing this game mode +#### "lobbyInviteUpdate" (lobbyInvite) +Emitted when the bot received an invite to a lobby -Emitted when the GC responds to `requestJoinableCustomGameModes`. Never seems to return more then ten results. +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) -### `inviteCreated` (`steam_id`, `group_id`, `is_online`) -* `steam_id` - The steam ID of the person the invite was sent to -* `group_id` - The group ID of the person the invite was sent to -* `is_online` - Whether or not the person the invite was sent to is online +| Param | Type | Description | +| --- | --- | --- | +| lobbyInvite | CSODOTALobbyInvite | The invitation to a lobby. | -Emitted when the GC has created the invitation. The invitation is only sent when -the invitee is online. + -### `partyUpdate` (`party`) -* `party` - The full party object (see `CSODOTAParty`). +#### "lobbyInviteCleared" +Emitted when the Lobby Invite is cleared, for example when +accepting/rejecting it or when the lobby is closed. +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +#### "partyUpdate" (party) Emitted when the GC sends a party snapshot. The GC is incredibly inefficient and will send the entire object even if it's a minor update. You can use this to detect when a party has been entered / created -successfully as well. Note that the `Party` property will be the old +successfully as well. Note that the [Party](#module_Dota2.Dota2Client+Party) property will be the old value until after this event completes to allow comparison between the two. +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) -### `partyCleared` () +| Param | Type | Description | +| --- | --- | --- | +| party | CSODOTAParty | The new state of the party. | + +#### "partyCleared" Emitted when leaving a party (aka, the party is cleared). This can happen when kicked, upon leaving a party, etc. There are other callbacks to tell when the bot has been kicked. +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + -### `partyInviteUpdate` (`party`) -* `partyInvite` - The full party invite object (see CSODOTAPartyInvite). - - +#### "partyInviteUpdate" (partyInvite) Emitted when the GC sends a party invite snapshot. The GC is incredibly inefficient and will send the entire object even if it's a minor update. You can use this to detect when an incoming party invite has been sent. -Note that the `PartyInvite` property will be the old +Note that the [PartyInvite](#module_Dota2.Dota2Client+PartyInvite) property will be the old value until after this event completes to allow comparison between the two. +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) -### `partyInviteCleared` () +| Param | Type | Description | +| --- | --- | --- | +| partyInvite | CSODOTAPartyInvite | The invitation to a party. | + +#### "partyInviteCleared" Emitted when the Party Invite is cleared, for example when -accepting/rejecting it or when the party is closed. +accepting/rejecting it or when the party is closed +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + -### `liveLeagueGamesUpdate` (`null`, `liveLeaguesResponse`) -* `null` - nothing -* `liveLeaguesResponse` - Integer representing number of live league games. +#### "chatJoined" (channelData) +Event that's emitted whenever the bot joins a chat channel +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) -### `leaguesInMonthData` (`month`, `year`, `leagues`) -* `month` - Int representing which month this data represents. -* `year` - Int representing which year this data represents. -* `leagues` - Array of CMsgLeague objects +| Param | Type | Description | +| --- | --- | --- | +| channelData | Object | A `CMsgDOTAJoinChatChannelResponse` object containing information about the chat channel. | -Emitted when the GC responds to `requestLeaguesInMonth` method. + -Notes: +#### "chatJoin" (channel, joiner_name, joiner_steam_id, otherJoined_object) +Event that's emitted whenever someone else joins a chat channel the bot is in -* The `month` property is used to filter the data to the leagues which have matches scheduled in the given month, however the `schedule` object contains schedules for a league's entire duration - i.e. before or after `month`. -* `month` is also zero-aligned, so January = 0, Febuary = 1, March = 2, etc. -* Not every participating team seems to be hooked up to Dota 2's team system, so there will be a few `{ teamId: 0 }` objects for some schedule blocks. +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) -The leagues object is visualized as follows: +| Param | Type | Description | +| --- | --- | --- | +| channel | string | Name of the chat channel someone joined | +| joiner_name | string | Persona name of the person that joined the channel | +| joiner_steam_id | [Long](#external_Long) | Steam ID of the person that joined the channel | +| otherJoined_object | CMsgDOTAOtherJoinedChatChannel | The raw message data. | -``` -leagues: [{ // An array of CMsgLeague objects - leagueId, // ID of the league associated - schedule: [{ // An array of CMsgLeagueScheduleBlock objects - blockId, // ID represending this block - startTime, // Unix timestamp of a scheduled match (or group of matches) - finals, // Boolean represending if this match is a final. - comment, // Comment about this scheduled block - often the team names & position in bracket - teams: [{ // An array of CMsgLeagueScheduleBlockTeamInfo objects - teamId, // ID of the associated team - name, // The teams name - tag, // The teams tag - logo // The teams logo - }] - }] -}] -``` + -### `topLeagueMatchesData` (`matches`) -* `matches` - A list of matches. Each match contains: - * `match_id` - Match ID - * `start_time` - Unix time of the start of the match - * `duration` - Duration of the match in seconds - * `game_mode` - Game mode - * `winning_team` - Team who won the match - * `players` - List of all the players in the game, contains id, hero, K/D/A and items - * `league` - Information on the league if this is a league match +#### "chatLeave" (channel, leaver_steam_id, otherLeft_object) +Event that's emitted whenever someone else leaves a chat channel the bot is in -Emitted when the GC responds to the `requestTopLeagueMatches` method. +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) -### `leagueData` () +| Param | Type | Description | +| --- | --- | --- | +| channel | string | Name of the chat channel someone left | +| leaver_steam_id | string | Persona name of the person that left the channel | +| otherLeft_object | CMsgDOTAOtherLeftChatChannel | The raw message data. | -TODO + -### `sourceTVGamesData` (`sourceTVGamesResponse`) -* `sourceTVGamesResponse` - The raw response object +#### "chatMessage" (channel, sender_name, message, chatData) +Event that's emitted whenever someone sends a message in a channel the bot is in -Emitted when the GC responds to the `requestSourceTVGames` method. Multiple events are emitted when `requestSourceTVGames` is passed with `start_game` > 0 or with one or more `lobby_id`s. +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) +| Param | Type | Description | +| --- | --- | --- | +| channel | string | Name of the chat channel the message was sent to | +| sender_name | string | Persona name of the sender of the message | +| message | string | The message that was sent | +| chatData | CMsgDOTAChatMessage | The raw message data containing the message and its metadata. | -### `inventoryUpdate` (`inv`) -* `inv` - Player inventory + -Emitted when the GC sends an inventory snapshot. The GC is incredibly -inefficient and will send the entire object even if it's a minor update. -You can use this to detect when a change was made to your inventory (e.g. drop) -Note that the `Inventory` property will be the old value until after this event -completes to allow comparison between the two. +#### "chatChannelsData" (channels) +Event that's emitted after requesting a list of chat channels via [requestChatChannels](#module_Dota2.Dota2Client+requestChatChannels) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| channels | Array.<Object> | An array of ChatChannel objects | +| channels[].channel_name | string | Name of the chat channel | +| channels[].num_members | number | Number of members in the channel | +| channels[].channel_type | DOTAChatChannelType_t | The type of the channel | + + + +#### "playerMatchHistoryData" (requestId, matchHistoryResponse) +Emitted in response to a [request for a player's match history](#module_Dota2.Dota2Client+requestPlayerMatchHistory) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| requestId | number | Id of the request to which this event is the answer | +| matchHistoryResponse | CMsgDOTAGetPlayerMatchHistoryResponse | The raw response data containing the user's match history. | + + + +#### "profileCardData" (account_id, profileCardResponse) +Emitted in response to a [request for a player's profile card](#module_Dota2.Dota2Client+requestProfileCard) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| account_id | number | Dota2 account ID of the player whose profile card was fetched. | +| profileCardResponse | CMsgDOTAProfileCard | The raw response data containing the user's profile card. | + + + +#### "hallOfFameData" (week, featured_players, featured_farmer, hallOfFameResponse) +Emitted in response to a [request for a player's profile card](#module_Dota2.Dota2Client+requestHallOfFame) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| week | number | Weeks since unix epoch for which the hall of fame data was fetched | +| featured_players | Array.<Object> | This week's featured players | +| featured_players[].account_id | number | Dota2 account id of the featured player | +| featured_players[].hero_id | number | ID of the hero | +| featured_players[].average_scaled_metric | number | Scaled metric of awesomeness | +| featured_players[].num_games | number | The number of games played | +| featured_farmer | Object | This week's featured farmer | +| featured_farmer.account_id | number | Dota2 account id of the featured farmer | +| featured_farmer.hero_id | number | ID of the hero | +| featured_farmer.gold_per_min | number | GPM for the featured match | +| featured_farmer.match_id | number | Match ID of the featured match | +| hallOfFameResponse | CMsgDOTAHallOfFameResponse | The raw response data containing the requested week's hall of fame. | + + + +#### "playerInfoData" (playerInfoData) +Emitted in response to a [request for a player's info](#module_Dota2.Dota2Client+requestPlayerInfo) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| playerInfoData | Object | A `CMsgGCPlayerInfo` object containing the player's info. | +| playerInfoData.player_infos | Array.<Object> | List of player information | +| playerInfoData.player_infos[].account_id | number | Dota2 account ID of the player | +| playerInfoData.player_infos[].name | string | The display name for the player | +| playerInfoData.player_infos[].country_code | string | The abbreviated country code for the user if available (i.e. `us`, `cn`, etc...) | +| playerInfoData.player_infos[].fantasy_role | number | The role of the player, either core or support, `1` and `2` respectively | +| playerInfoData.player_infos[].team_id | number | The numerical id of the user's team | +| playerInfoData.player_infos[].team_name | string | The name of the team the user is on, ex: `Cloud9` | +| playerInfoData.player_infos[].team_tag | string | The abbreviated tag of a team prepended to a player's name, ex: `C9` | +| playerInfoData.player_infos[].sponsor | string | The sponsor listed in the player's official info, ex: `HyperX` | +| playerInfoData.player_infos[].is_locked | boolean | Whether or not the user's official player info has been locked from editing, `true` or `false` | +| playerInfoData.player_infos[].is_pro | boolean | Whether the player is considered a pro player by Valve, `true` or `false` | +| playerInfoData.player_infos[].locked_until | number | Timestamp indicating end of lock period | +| playerInfoData.player_infos[].timestamp | number | Unknown | + + + +#### "trophyListData" (trophyListResponse) +Emitted in response to a [request for a player's trophy list](#module_Dota2.Dota2Client+requestTrophyList) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| trophyListResponse | Object | A `CMsgClientToGCGetTrophyListResponse` object containing the player's trophy list. | +| trophyListResponse.account_id | number | Dota2 account ID of the player | +| trophyListResponse.trophies | Array.<Object> | List of player trophies | +| trophyListResponse.trophies[].trophy_id | number | Id of the trophy | +| trophyListResponse.trophies[].trophy_score | number | The score this trophy has counted. This is usually a level, but can represent other things, like number of challenges completed, or coins collected, etc... | +| trophyListResponse.trophies[].last_updated | number | The last time the trophy has been updated, in Unix time | +| trophyListResponse.profile_name | string | The name displayed on the user's dota profile page and profile card | + + + +#### "playerStatsData" (account_id, playerStatsResponse) +Emitted in response to a [request for a player's stats](#module_Dota2.Dota2Client+requestPlayerStats) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| account_id | number | Dota2 account ID of the player | +| playerStatsResponse | [CMsgGCToClientPlayerStatsResponse](#module_Dota2.schema.CMsgGCToClientPlayerStatsResponse) | The player's stats. | + + + +#### "joinableCustomGameModes" (joinableCustomGameModes) +Emitted in response to a [request for joinable custom game modes](#module_Dota2.Dota2Client+requestJoinableCustomGameModes). + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| joinableCustomGameModes | Array.<CMsgJoinableCustomGameModesResponseEntry> | List of joinable custom game modes | + + + +#### "playerCardRoster" (playerCardRoster) +Emitted in response to a [request for a player's fantasy roster](#module_Dota2.Dota2Client+requestPlayerCardRoster) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| playerCardRoster | CMsgClientToGCGetPlayerCardRosterResponse | The raw response data containing the fantasy draft and score if available. | + + + +#### "playerCardDrafted" (playerCardRoster) +Emitted in response to a [draft of a player card](#module_Dota2.Dota2Client+draftPlayerCard) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| playerCardRoster | number | The result of the operation. See `CMsgClientToGCSetPlayerCardRosterResponse.result`. | + + + +#### "popup" (id, popup) +Emitted when the server wants the client to create a pop-up + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| id | number | Type of the pop-up. | +| popup | CMsgDOTAPopup | The raw pop-up object. Can contain further specifications like formattable text | + + + +#### "leaguesInMonthData" (month, year, leagues) +Emitted in response to a [request for the leagues in a given month](#module_Dota2.Dota2Client+requestLeaguesInMonth). +The leagues that are returned are those which have one or more matches in the given month. +They can however also have other matches in a different month. + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| month | number | Month this data represents. | +| year | number | Year this data represents | +| leagues | Array.<Object> | List of leagues that have matches in the given month | +| leagues[].league_id | number | ID of the league | +| leagues[].schedule | Array.<Object> | The scheduled games in this league. Might contain matches in other months. | +| leagues[].schedule[].block_id | number | ID of the schedule block | +| leagues[].schedule[].start_time | number | Unix timestamp of the start time of this scheduled match | +| leagues[].schedule[].finals | boolean | Whether or not this is a finals game | +| leagues[].schedule[].comment | string | Comment about this scheduled block; often the team names & position in bracket | +| leagues[].schedule[].teams | Array.<Object> | The teams duking it out in this match | +| leagues[].schedule[].teams[].team_id | number | ID of the team. Not every participating team seems to be hooked up to Dota 2's team system, so 0 entries can happen | +| leagues[].schedule[].teams[].name | string | Name of the team | +| leagues[].schedule[].teams[].logo | [Long](#external_Long) | Logo of the team | + + + +#### "liveLeagueGamesUpdate" (live_league_games) +Emitted when the GC sends a `CMsgDOTALiveLeagueGameUpdate`. + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| live_league_games | number | The number of live league games | + + + +#### "leagueData" (leagues) +Emitted in response to a [request for league info](#module_Dota2.Dota2Client+requestLeagueInfo). + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| leagues | Array.<Object> | List of all leagues | +| leagues[].league_id | number | ID of the league | +| leagues[].last_match_time | number | Unix timestamp of when the last match took place | +| leagues[].prize_pool_usd | number | Price pool in US$ | +| leagues[].has_live_matches | boolean | Whether or not if there are currently live matches | +| leagues[].is_compendium_public | boolean | Whether or not there is a public compendium | +| leagues[].compendium_version | number | Verion nr of the compendium | +| leagues[].compendium_content_version | number | Version nr of the compendium contents | + + + +#### "topLeagueMatchesData" (matches) +Emitted in response to a [request for top league matches](#module_Dota2.Dota2Client+requestTopLeagueMatches). + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| matches | Array.<Object> | List of top matches | +| matches[].match_id | [Long](#external_Long) | Match ID | +| matches[].start_time | number | Unix timestamp of the start of the match | +| matches[].duration | number | Duration of the match in seconds | +| matches[].game_mode | DOTA_GameMode | Game mode | +| matches[].players | CMsgDOTAMatchMinimal.Player | List of all the players in the game, contains id, hero, K/D/A and items | +| matches[].tourney | CMsgDOTAMatchMinimal.Tourney | Information on the league if this is a league match | +| matches[].match_outcome | EMatchOutcome | Who won | + + + +#### "practiceLobbyJoinResponse" (result, response) +Event that's emitted whenever the bot joins a lobby + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| result | DOTAJoinLobbyResult | Result code | +| response | Object | The raw response object | +| response.result | DOTAJoinLobbyResult | Result code | + + + +#### "practiceLobbyListData" (practiceLobbyListResponse) +Event that's emitted in response to a [request for the list of lobbies](#module_Dota2.Dota2Client+requestPracticeLobbyList) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| practiceLobbyListResponse | Object | Raw response object | +| practiceLobbyListResponse.tournament_games | boolean | Whether or not there are tournament games included in the list | +| practiceLobbyListResponse.lobbies | Array.<CMsgPracticeLobbyListResponseEntry> | List of practice lobbies and their details | + + + +#### "practiceLobbyResponse" (result, response) +Emitted when an operation changing the state of a lobby was sent to the GC and +processed. This event only contains the acknowledgement by the GC. The actual +update of the lobby state is communicated via [module:Dota2.Dota2Client#practiceLobbyUpdate](module:Dota2.Dota2Client#practiceLobbyUpdate) events. + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| result | DOTAJoinLobbyResult | Result code | +| response | Object | The raw response object | +| response.result | [EResult](#module_Dota2.EResult) | Result code | + + + +#### "friendPracticeLobbyListData" (practiceLobbyListResponse) +Event that's emitted in response to a [request for the list of your friends' lobbies](#module_Dota2.Dota2Client+requestPracticeLobbyList) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| practiceLobbyListResponse | Object | Raw response object | +| practiceLobbyListResponse.lobbies | Array.<CMsgPracticeLobbyListResponseEntry> | List of practice lobbies and their details | + + + +#### "inviteCreated" (steam_id, group_id, is_online) +Event that's emitted whenever the bot attempts to invite someone to a lobby + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| steam_id | [Long](#external_Long) | Steam ID of the person that was invited to the lobby | +| group_id | [Long](#external_Long) | Group ID of the invitation | +| is_online | boolean | Whether or not the invitee is online | + + + +#### "matchesData" (requestId, total_results, results_remaining, matches, series, matchResponse) +Emitted in response to a [request for matches](#module_Dota2.Dota2Client+requestMatches) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| requestId | number | Id of the request to which this event is the answer | +| total_results | number | Total number of results corresponding to the query (max 500) | +| results_remaining | number | Total number of results not in this response | +| matches | Array.<CMsgDOTAMatch> | List of match information objects | +| series | Array.<Object> | List of series | +| series[].matches | Array.<CMsgDOTAMatch> | List of match information objects for the matches in this series | +| series[].series_id | number | ID of the series | +| series[].series_type | number | Type of the series | +| matchResponse | CMsgDOTARequestMatchesResponse | A `CMsgDOTARequestMatchesResponse` object containing the raw response. | + + + +#### "matchDetailsData" (match_id, matchDetailsResponse) +Emitted in response to a [request for a match's details](#module_Dota2.Dota2Client+requestMatchDetails) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| match_id | number | Match ID for which the details where asked | +| matchDetailsResponse | CMsgGCMatchDetailsResponse | A `CMsgGCMatchDetailsResponse` object containing the raw response. | + + + +#### "matchMinimalDetailsData" (last_match, matchMinimalDetailsResponse) +Emitted in response to a [request for a/multiples match's minimal details](#module_Dota2.Dota2Client+requestMatchMinimalDetails) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| last_match | boolean | Whether or not the last of the requested matches is included in this response | +| matchMinimalDetailsResponse | CMsgClientToGCMatchesMinimalResponse | A `CMsgClientToGCMatchesMinimalResponse` object containing the raw response. | + + + +#### "matchmakingStatsData" (matchgroups_version, match_groups, matchmakingStatsResponse) +Emitted in response to a [request for the match making stats](#module_Dota2.Dota2Client+requestMatchmakingStats) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| matchgroups_version | number | Version nr of the match groups (these evolve over time). For the current list check [regions.txt](https://github.com/SteamDatabase/GameTracking-Dota2/blob/master/game/dota/pak01_dir/scripts/regions.txt) | +| match_groups | Array.<Object> | The different match groups and their stats | +| match_groups[].players_searching | number | The number of people searching for a match | +| match_groups[].auto_region_select_ping_penalty | number | Ping penalty for people searching this region | +| matchmakingStatsResponse | CMsgDOTAMatchmakingStatsResponse | A `CMsgDOTAMatchmakingStatsResponse` object containing the raw response. | + + + +#### "topFriendMatchesData" (matches) +Emitted in response to a [request for the current top matches played by your friends](#module_Dota2.Dota2Client+requestTopFriendMatches) + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| matches | Array.<CMsgDOTAMatchMinimal> | A list of `CMsgDOTAMatchMinimal` objects containing the minimal match details of the matches your friends are currently playing. | + + + +#### "sourceTVGamesData" (sourceTVGamesResponse) +sourceTVGamesData event + +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) + +| Param | Type | Description | +| --- | --- | --- | +| sourceTVGamesResponse | CMsgGCToClientFindTopSourceTVGamesResponse | The raw response data or null if a bad response was received | -### `playerCardRoster` (`playerCardRoster`) -* `playerCardRoster` - Fantasy challenge line-up for a specific day -* `result` - Status code indicating whether or not the request was succesful (0 = SUCCESS) - * `player_card_item_id` - Item ID of the player card. Can be used to cross-reference with `Inventory` - * `score` - Score the card got for this specific day - * `finalized` - Whether or not the matches for this day are over - * `percentile` - Percentile of all players your score falls in - -Emitted when the GC responds to the `requestPlayerCardRoster` method. - -### `playerCardDrafted` (`result`) -* `result` - Status code indicating whether or not the card got drafted (0 = SUCCESS) - -Emitted when the GC responds to the `draftPlayerCard` method. - -## Enums -### ServerRegion -* `UNSPECIFIED: 0` -* `USWEST: 1` -* `USEAST: 2` -* `EUROPE: 3` -* `KOREA: 4` -* `SINGAPORE: 5` -* `DUBAI: 6` -* `AUSTRALIA: 7` -* `STOCKHOLM: 8` -* `AUSTRIA: 9` -* `BRAZIL: 10` -* `SOUTHAFRICA: 11` -* `PWTELECOMSHANGHAI: 12` -* `PWUNICOM: 13` -* `CHILE: 14` -* `PERU: 15` -* `INDIA: 16` -* `PWTELECOMGUANGZHOU: 17` -* `PWTELECOMZHEJIANG: 18` -* `JAPAN: 19` -* `PWTELECOMWUHAN: 20` - -Use this to pass valid server region data to `createPracticeLobby`. - -### GameMode -* `DOTA_GAMEMODE_NONE: 0` - None -* `DOTA_GAMEMODE_AP: 1` - All Pick -* `DOTA_GAMEMODE_CM: 2` - Captain's Mode -* `DOTA_GAMEMODE_RD: 3` - Random Draft -* `DOTA_GAMEMODE_SD: 4` - Single Draft -* `DOTA_GAMEMODE_AR: 5` - All Random -* `DOTA_GAMEMODE_INTRO: 6` - Unknown -* `DOTA_GAMEMODE_HW: 7` - Diretide -* `DOTA_GAMEMODE_REVERSE_CM: 8` - Reverse Captain's Mode -* `DOTA_GAMEMODE_XMAS: 9` - The Greeviling -* `DOTA_GAMEMODE_TUTORIAL: 10` - Tutorial -* `DOTA_GAMEMODE_MO: 11` - Mid Only -* `DOTA_GAMEMODE_LP: 12` - Least Played -* `DOTA_GAMEMODE_POOL1: 13` - Limited Heroes -* `DOTA_GAMEMODE_FH: 14` - Compendium -* `DOTA_GAMEMODE_CUSTOM: 15` - Unknown, probably ti4 techies reveal. -* `DOTA_GAMEMODE_CD: 16` - Captain's Draft -* `DOTA_GAMEMODE_BD: 17` - Balanced Draft -* `DOTA_GAMEMODE_ABILITY_DRAFT: 18` - Ability Draft -* `DOTA_GAMEMODE_EVENT: 19` - Unknown -* `DOTA_GAMEMODE_ARDM: 20` - All Random Death Match -* `DOTA_GAMEMODE_1V1MID: 21` - 1v1 Mid -* `DOTA_GAMEMODE_ALL_DRAFT: 22` - All Draft a.k.a. ranked all pick - -Use this to pass valid game mode data to `createPracticeLobby`. This enum is built-in the protobuf schema and can be referenced by `Dota2.DOTA_GameMode`. + +#### "teamData" (teams, league_id) +Emitted in response to a [request for your teams](#module_Dota2.Dota2Client+requestMyTeams). +**Kind**: event emitted by [Dota2Client](#module_Dota2.Dota2Client) +| Param | Type | Description | +| --- | --- | --- | +| teams | Array.<CMsgDOTATeamInfo> | A list of `CMsgDOTATeamInfo` objects containing information about the teams you're in (name, members, stats, ...) | +| league_id | number | No clue why this is here, nor what it signifies | + + + +#### Dota2Client.ToAccountID(steamID) ⇒ number +Converts a 64bit Steam ID to a Dota2 account ID by deleting the 32 most significant bits + +**Kind**: static method of [Dota2Client](#module_Dota2.Dota2Client) +**Returns**: number - Dota2 account ID corresponding with steamID + +| Param | Type | Description | +| --- | --- | --- | +| steamID | string | String representation of a 64bit Steam ID | + + + +#### Dota2Client.ToSteamID(accid) ⇒ [Long](#external_Long) +Converts a Dota2 account ID to a 64bit Steam ID + +**Kind**: static method of [Dota2Client](#module_Dota2.Dota2Client) +**Returns**: [Long](#external_Long) - 64bit Steam ID corresponding to the given Dota 2 account ID + +| Param | Type | Description | +| --- | --- | --- | +| accid | string | String representation of a Dota 2 account ID | + + + +### Dota2.schema +Protobuf schema. See [Protobufjs#Root](http://dcode.io/protobuf.js/Root.html). +This object can be used to obtain special protobuf types. +Object types can be created by `Dota2.schema.lookupType("TypeName").encode(payload :Object).finish();`. +Enum types can be referenced by `Dota2.schema.lookupEnum("EnumName")`, which returns an object array representing the enum. + +**Kind**: static property of [Dota2](#module_Dota2) + + +#### schema.CMsgGCToClientPlayerStatsResponse : Object +Player statistics + +**Kind**: static typedef of [schema](#module_Dota2.schema) +**Properties** + +| Name | Type | Description | +| --- | --- | --- | +| account_id | number | Dota2 account ID of the player | +| player_stats | Array.<number> | | +| match_count | number | Number of matches played | +| mean_gpm | number | Mean GPM per match over the last 20 matches | +| mean_xppm | number | Mean XPPM per match over the last 20 matches | +| mean_lasthits | number | Mean last hits per match over the last 20 matches | +| rampages | number | All time number of rampages | +| triple_kills | number | All time number of triple kills | +| first_blood_claimed | number | All time number of times the player claimed first blood | +| first_blood_given | number | All time number of times the player fed first blood | +| couriers_killed | number | All time number of couriers killed | +| aegises_snatched | number | All time number of aegises snatched | +| cheeses_eaten | number | All time amount of cheese eaten | +| creeps_stacked | number | All time number of camps stacked | +| fight_score | number | Fighting score over the last 20 matches | +| farm_score | number | Farming score over the last 20 matches | +| support_score | number | Support score over the last 20 matches | +| push_score | number | Push score over the last 20 matches | +| versatility_score | number | Hero versatility over the last 20 matches | + + + +### Dota2.EResult : enum +Enum for all possible `EResult` values + +**Kind**: static enum of [Dota2](#module_Dota2) +**Read only**: true +**Properties** + +| Name | Type | Default | +| --- | --- | --- | +| k_EResultOK | number | 1 | +| k_EResultFail | number | 2 | +| k_EResultNoConnection | number | 3 | +| k_EResultInvalidPassword | number | 5 | +| k_EResultLoggedInElsewhere | number | 6 | +| k_EResultInvalidProtocolVer | number | 7 | +| k_EResultInvalidParam | number | 8 | +| k_EResultFileNotFound | number | 9 | +| k_EResultBusy | number | 10 | +| k_EResultInvalidState | number | 11 | +| k_EResultInvalidName | number | 12 | +| k_EResultInvalidEmail | number | 13 | +| k_EResultDuplicateName | number | 14 | +| k_EResultAccessDenied | number | 15 | +| k_EResultTimeout | number | 16 | +| k_EResultBanned | number | 17 | +| k_EResultAccountNotFound | number | 18 | +| k_EResultInvalidSteamID | number | 19 | +| k_EResultServiceUnavailable | number | 20 | +| k_EResultNotLoggedOn | number | 21 | +| k_EResultPending | number | 22 | +| k_EResultEncryptionFailure | number | 23 | +| k_EResultInsufficientPrivilege | number | 24 | +| k_EResultLimitExceeded | number | 25 | +| k_EResultRevoked | number | 26 | +| k_EResultExpired | number | 27 | +| k_EResultAlreadyRedeemed | number | 28 | +| k_EResultDuplicateRequest | number | 29 | +| k_EResultAlreadyOwned | number | 30 | +| k_EResultIPNotFound | number | 31 | +| k_EResultPersistFailed | number | 32 | +| k_EResultLockingFailed | number | 33 | +| k_EResultLogonSessionReplaced | number | 34 | +| k_EResultConnectFailed | number | 35 | +| k_EResultHandshakeFailed | number | 36 | +| k_EResultIOFailure | number | 37 | +| k_EResultRemoteDisconnect | number | 38 | +| k_EResultShoppingCartNotFound | number | 39 | +| k_EResultBlocked | number | 40 | +| k_EResultIgnored | number | 41 | +| k_EResultNoMatch | number | 42 | +| k_EResultAccountDisabled | number | 43 | +| k_EResultServiceReadOnly | number | 44 | +| k_EResultAccountNotFeatured | number | 45 | +| k_EResultAdministratorOK | number | 46 | +| k_EResultContentVersion | number | 47 | +| k_EResultTryAnotherCM | number | 48 | +| k_EResultPasswordRequiredToKickSession | number | 49 | +| k_EResultAlreadyLoggedInElsewhere | number | 50 | +| k_EResultSuspended | number | 51 | +| k_EResultCancelled | number | 52 | +| k_EResultDataCorruption | number | 53 | +| k_EResultDiskFull | number | 54 | +| k_EResultRemoteCallFailed | number | 55 | + + + +### Dota2.ServerRegion : enum +Enum for all server regions. This enum is kept up to date on a best effort base. +For the up-to-date values, check your game's regions.txt or [SteamDB's version](https://github.com/SteamDatabase/GameTracking-Dota2/blob/master/game/dota/pak01_dir/scripts/regions.txt) + +**Kind**: static enum of [Dota2](#module_Dota2) +**Read only**: true +**Properties** + +| Name | Type | Default | +| --- | --- | --- | +| UNSPECIFIED | number | 0 | +| USWEST | number | 1 | +| USEAST | number | 2 | +| EUROPE | number | 3 | +| KOREA | number | 4 | +| SINGAPORE | number | 5 | +| DUBAI | number | 6 | +| AUSTRALIA | number | 7 | +| STOCKHOLM | number | 8 | +| AUSTRIA | number | 9 | +| BRAZIL | number | 10 | +| SOUTHAFRICA | number | 11 | +| PWTELECOMSHANGHAI | number | 12 | +| PWUNICOM | number | 13 | +| CHILE | number | 14 | +| PERU | number | 15 | +| INDIA | number | 16 | +| PWTELECOMGUANGZHOU | number | 17 | +| PWTELECOMZHEJIANG | number | 18 | +| JAPAN | number | 19 | +| PWTELECOMWUHAN | number | 20 | + + + +### Dota2.SeriesType : enum +Enum for different types of series. + +**Kind**: static enum of [Dota2](#module_Dota2) +**Read only**: true +**Properties** + +| Name | Type | Default | +| --- | --- | --- | +| NONE | number | 0 | +| BEST_OF_THREE | number | 1 | +| BEST_OF_FIVE | number | 2 | + + + +### Dota2.BotDifficulty : enum +Enum for different bot difficulty levels. + +**Kind**: static enum of [Dota2](#module_Dota2) +**Read only**: true +**Properties** + +| Name | Type | Default | +| --- | --- | --- | +| PASSIVE | number | 0 | +| EASY | number | 1 | +| MEDIUM | number | 2 | +| HARD | number | 3 | +| UNFAIR | number | 4 | + + + +### Dota2~requestCallback : function +**Kind**: inner typedef of [Dota2](#module_Dota2) + +| Param | Type | Description | +| --- | --- | --- | +| errorCode | number | Null if everything went well, else the error code | +| responseMessage | Object | The response message the GC sent | + + + +### Dota2~Long +A Long class for representing a 64 bit two's-complement integer value +derived from the Closure Library for stand-alone use and extended with unsigned support. + +**Kind**: inner external of [Dota2](#module_Dota2) +**See**: [long](https://www.npmjs.com/package/long) npm package diff --git a/handlers/cache.js b/handlers/cache.js index f5cb44a3..a6965549 100644 --- a/handlers/cache.js +++ b/handlers/cache.js @@ -49,10 +49,10 @@ function handleSubscribedType(obj_type, object_data) { break; // Lobby invite snapshot. case cacheTypeIDs.CSODOTALobbyInvite: - var lobby = Dota2.schema.lookupType("CSODOTALobbyInvite").decode(object_data[0]); - if (this.debug) util.log("Received lobby invite snapshot for group ID " + lobby.group_id); - this.emit("lobbyInviteUpdate", lobby); - this.LobbyInvite = lobby; + var lobbyInvite = Dota2.schema.lookupType("CSODOTALobbyInvite").decode(object_data[0]); + if (this.debug) util.log("Received lobby invite snapshot for group ID " + lobbyInvite.group_id); + this.emit("lobbyInviteUpdate", lobbyInvite); + this.LobbyInvite = lobbyInvite; break; // Party snapshot. case cacheTypeIDs.CSODOTAParty: @@ -86,6 +86,73 @@ Dota2.Dota2Client.prototype._handleWelcomeCaches = function handleWelcomeCaches( }); }; +// Events +/** + * Emitted when the GC sends an inventory snapshot. The GC is incredibly + * inefficient and will send the entire object even if it's a minor update. + * You can use this to detect when a change was made to your inventory (e.g. drop) + * Note that the {@link module:Dota2.Dota2Client#Inventory|Inventory} property will be the old value until after this event + * completes to allow comparison between the two. + * @event module:Dota2.Dota2Client#inventoryUpdate + * @param {CSOEconItem[]} inventory - A list of `CSOEconItem` objects + */ + /** + * Emitted when the GC sends a lobby snapshot. The GC is incredibly + * inefficient and will send the entire object even if it's a minor update. + * You can use this to detect when a lobby has been entered / created + * successfully as well. Note that the {@link module:Dota2.Dota2Client#Lobby|Lobby} property will be the old + * value until after this event completes to allow comparison between the + * two. + * @event module:Dota2.Dota2Client#practiceLobbyUpdate + * @param {CSODOTALobby} lobby - The new state of the lobby. + */ + /** + * Emitted when leaving a lobby (aka, the lobby is cleared). This can + * happen when kicked, upon leaving a lobby, etc. There are other events + * to tell when the bot has been kicked. + * @event module:Dota2.Dota2Client#practiceLobbyCleared + */ + /** + * Emitted when the bot received an invite to a lobby + * @event module:Dota2.Dota2Client#lobbyInviteUpdate + * @param {CSODOTALobbyInvite} lobbyInvite - The invitation to a lobby. + */ + /** + * Emitted when the Lobby Invite is cleared, for example when + * accepting/rejecting it or when the lobby is closed. + * @event module:Dota2.Dota2Client#lobbyInviteCleared + */ + /** + * Emitted when the GC sends a party snapshot. The GC is incredibly + * inefficient and will send the entire object even if it's a minor update. + * You can use this to detect when a party has been entered / created + * successfully as well. Note that the {@link module:Dota2.Dota2Client#Party|Party} property will be the old + * value until after this event completes to allow comparison between the + * two. + * @event module:Dota2.Dota2Client#partyUpdate + * @param {CSODOTAParty} party - The new state of the party. + */ + /** + * Emitted when leaving a party (aka, the party is cleared). This can + * happen when kicked, upon leaving a party, etc. There are other callbacks + * to tell when the bot has been kicked. + * @event module:Dota2.Dota2Client#partyCleared + */ + /** + * Emitted when the GC sends a party invite snapshot. The GC is incredibly + * inefficient and will send the entire object even if it's a minor update. + * You can use this to detect when an incoming party invite has been sent. + * Note that the {@link module:Dota2.Dota2Client#PartyInvite|PartyInvite} property will be the old + * value until after this event completes to allow comparison between the two. + * @event module:Dota2.Dota2Client#partyInviteUpdate + * @param {CSODOTAPartyInvite} partyInvite - The invitation to a party. + */ + /** + * Emitted when the Party Invite is cleared, for example when + * accepting/rejecting it or when the party is closed + * @event module:Dota2.Dota2Client#partyInviteCleared + */ + var handlers = Dota2.Dota2Client.prototype._handlers; var onCacheSubscribed = function onCacheSubscribed(message) { @@ -130,16 +197,16 @@ var onCacheUnsubscribed = function onCacheUnsubscribed(message) { if (this.debug) util.log("Cache unsubscribed, " + unsubscribe.owner_soid.id); - if (this.Lobby && "" + unsubscribe.owner_soid.id === "" + this.Lobby.lobby_id) { + if (this.Lobby && unsubscribe.owner_soid.id.eq(this.Lobby.lobby_id)) { this.Lobby = null; this.emit("practiceLobbyCleared"); - } else if (this.LobbyInvite && "" + unsubscribe.owner_soid.id === "" + this.LobbyInvite.group_id) { + } else if (this.LobbyInvite && unsubscribe.owner_soid.id.eq(this.LobbyInvite.group_id)) { this.LobbyInvite = null; this.emit("lobbyInviteCleared"); - } else if (this.Party && "" + unsubscribe.owner_soid.id === "" + this.Party.party_id) { + } else if (this.Party && unsubscribe.owner_soid.id.eq(this.Party.party_id)) { this.Party = null; this.emit("partyCleared"); - } else if (this.PartyInvite && "" + unsubscribe.owner_soid.id === "" + this.PartyInvite.group_id) { + } else if (this.PartyInvite && unsubscribe.owner_soid.id.eq(this.PartyInvite.group_id)) { this.PartyInvite = null; this.emit("partyInviteCleared"); } diff --git a/handlers/chat.js b/handlers/chat.js index 7d6357d9..256f2638 100644 --- a/handlers/chat.js +++ b/handlers/chat.js @@ -18,9 +18,9 @@ Dota2.Dota2Client.prototype._getChannelByName = function(channel_name, channel_t Dota2.Dota2Client.prototype._getChannelById = function(channel_id) { // Returns the channel corresponding to the given channel_id return this.chatChannels.filter( - // channel_id is a uint64 which is a compound object. Using '===' or '==' doesn't work to check the equality necessitating the cast to String + // channel_id is a uint64 so it's mapped to a Long.js type function(item) { - return ("" + item.channel_id === "" + channel_id); + return (item.channel_id.eq(channel_id)); } )[0]; } @@ -37,8 +37,16 @@ Dota2.Dota2Client.prototype._leaveChatChannelById = function(channelId) { } }; +/** + * Joins a chat channel. If the chat channel with the given name doesn't exist, it + * is created. Listen for the `chatMessage` event for other people's chat messages. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#joinChat + * @param {string} channel_name - Name of the chat channel + * @param {DOTAChatChannelType_t} [channel_type=DOTAChatChannelType_t.DOTAChatChannelType_Custom] - The type of the channel being joined + */ Dota2.Dota2Client.prototype.joinChat = function(channel_name, channel_type) { - channel_type = channel_type || Dota2.schema.lookupEnum("DOTAChatChannelType_t").DOTAChannelType_Custom; + channel_type = channel_type == null ? Dota2.schema.lookupEnum("DOTAChatChannelType_t").DOTAChannelType_Custom : channel_type; /* Attempts to join a chat channel. Expect k_EMsgGCJoinChatChannelResponse from GC */ if (this.debug) util.log("Joining chat channel: " + channel_name); @@ -51,6 +59,14 @@ Dota2.Dota2Client.prototype.joinChat = function(channel_name, channel_type) { Dota2.schema.lookupType("CMsgDOTAJoinChatChannel").encode(payload).finish()); }; +/** + * Leaves a chat channel. If you've joined different channels with the same name, + * specify the type to prevent unexpected behaviour. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#leaveChat + * @param {string} channel_name - Name of the chat channel + * @param {DOTAChatChannelType_t} [channel_type] - The type of the channel being joined + */ Dota2.Dota2Client.prototype.leaveChat = function(channel_name, channel_type) { /* Attempts to leave a chat channel. GC does not send a response. */ if (this.debug) util.log("Leaving chat channel: " + channel_name); @@ -63,7 +79,16 @@ Dota2.Dota2Client.prototype.leaveChat = function(channel_name, channel_type) { this._leaveChatChannelById(cache.channel_id) }; -Dota2.Dota2Client.prototype.sendMessage = function(channel_name, message, channel_type) { +/** + * Sends a message to the specified chat channel. Won't send if you're not in the channel you try to send to. + * If you've joined different channels with the same name, specify the type to prevent unexpected behaviour. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#sendMessage + * @param {string} message - The message you want to send + * @param {string} channel_name - Name of the chat channel + * @param {DOTAChatChannelType_t} [channel_type] - The type of the channel being joined + */ +Dota2.Dota2Client.prototype.sendMessage = function(message, channel_name, channel_type) { /* Attempts to send a message to a chat channel. GC does not send a response. */ if (this.debug) util.log("Sending message to " + channel_name); // Check cache @@ -81,6 +106,13 @@ Dota2.Dota2Client.prototype.sendMessage = function(channel_name, message, channe Dota2.schema.lookupType("CMsgDOTAChatMessage").encode(payload).finish()); }; +/** + * Shares the lobby you're currently in with the chat so other people can join. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#shareLobby + * @param {string} channel_name - Name of the chat channel + * @param {DOTAChatChannelType_t} [channel_type] - The type of the channel being joined + */ Dota2.Dota2Client.prototype.shareLobby = function(channel_name, channel_type) { /* Attempts to send a message to a chat channel. GC does not send a response. */ if (this.debug) util.log("Sharing lobby to " + channel_name); @@ -104,6 +136,14 @@ Dota2.Dota2Client.prototype.shareLobby = function(channel_name, channel_type) { Dota2.schema.lookupType("CMsgDOTAChatMessage").encode(payload).finish()); }; +/** + * Sends a coin flip to the specified chat channel. Won't send if you're not in the channel you try to send to. + * If you've joined different channels with the same name, specify the type to prevent unexpected behaviour. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#flipCoin + * @param {string} channel_name - Name of the chat channel + * @param {DOTAChatChannelType_t} [channel_type] - The type of the channel being joined + */ Dota2.Dota2Client.prototype.flipCoin = function(channel_name, channel_type) { /* Attempts to send a coin flip to a chat channel. Expect a chatmessage in response. */ if (this.debug) util.log("Sending coin flip to " + channel_name); @@ -122,7 +162,17 @@ Dota2.Dota2Client.prototype.flipCoin = function(channel_name, channel_type) { Dota2.schema.lookupType("CMsgDOTAChatMessage").encode(payload).finish()); }; -Dota2.Dota2Client.prototype.rollDice = function(channel_name, min, max, channel_type) { +/** + * Sends a dice roll to the specified chat channel. Won't send if you're not in the channel you try to send to. + * If you've joined different channels with the same name, specify the type to prevent unexpected behaviour. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#rollDice + * @param {number} min - Lower bound of the dice roll + * @param {number} max - Upper bound of the dice roll + * @param {string} channel_name - Name of the chat channel + * @param {DOTAChatChannelType_t} [channel_type] - The type of the channel being joined + */ +Dota2.Dota2Client.prototype.rollDice = function(min, max, channel_name, channel_type) { /* Attempts to send a dice roll to a chat channel. Expect a chatmessage in response. */ if (this.debug) util.log("Sending dice roll to " + channel_name); // Check cache @@ -143,6 +193,11 @@ Dota2.Dota2Client.prototype.rollDice = function(channel_name, min, max, channel_ Dota2.schema.lookupType("CMsgDOTAChatMessage").encode(payload).finish()); }; +/** + * Requests a list of chat channels from the GC. Listen for the `chatChannelsData` event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestChatChannels + */ Dota2.Dota2Client.prototype.requestChatChannels = function() { /* Requests a list of chat channels from the GC. */ if (this.debug) util.log("Requesting channel list"); @@ -152,8 +207,45 @@ Dota2.Dota2Client.prototype.requestChatChannels = function() { Dota2.schema.lookupType("CMsgDOTAChatMessage").encode(payload).finish()); }; -// Handlers +// Events +/** + * Event that's emitted whenever the bot joins a chat channel + * @event module:Dota2.Dota2Client#chatJoined + * @param {Object} channelData - A `CMsgDOTAJoinChatChannelResponse` object containing information about the chat channel. + */ +/** + * Event that's emitted whenever someone else joins a chat channel the bot is in + * @event module:Dota2.Dota2Client#chatJoin + * @param {string} channel - Name of the chat channel someone joined + * @param {string} joiner_name - Persona name of the person that joined the channel + * @param {external:Long} joiner_steam_id - Steam ID of the person that joined the channel + * @param {CMsgDOTAOtherJoinedChatChannel} otherJoined_object - The raw message data. + */ +/** + * Event that's emitted whenever someone else leaves a chat channel the bot is in + * @event module:Dota2.Dota2Client#chatLeave + * @param {string} channel - Name of the chat channel someone left + * @param {string} leaver_steam_id - Persona name of the person that left the channel + * @param {CMsgDOTAOtherLeftChatChannel} otherLeft_object - The raw message data. + */ +/** + * Event that's emitted whenever someone sends a message in a channel the bot is in + * @event module:Dota2.Dota2Client#chatMessage + * @param {string} channel - Name of the chat channel the message was sent to + * @param {string} sender_name - Persona name of the sender of the message + * @param {string} message - The message that was sent + * @param {CMsgDOTAChatMessage} chatData - The raw message data containing the message and its metadata. + */ +/** + * Event that's emitted after requesting a list of chat channels via {@link module:Dota2.Dota2Client#requestChatChannels} + * @event module:Dota2.Dota2Client#chatChannelsData + * @param {Object[]} channels - An array of ChatChannel objects + * @param {string} channels[].channel_name - Name of the chat channel + * @param {number} channels[].num_members - Number of members in the channel + * @param {DOTAChatChannelType_t} channels[].channel_type - The type of the channel + */ +// Handlers var handlers = Dota2.Dota2Client.prototype._handlers; var onJoinChatChannelResponse = function onJoinChatChannelResponse(message) { diff --git a/handlers/community.js b/handlers/community.js index d0e1b1e3..6e917a4d 100644 --- a/handlers/community.js +++ b/handlers/community.js @@ -11,6 +11,22 @@ Dota2._playerHistoryOptions = { }; // Methods +/** + * Requests the given player's match history. The responses are paginated, + * but you can use the `start_at_match_id` and `matches_requested` options to loop through them. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:playerMatchHistoryData|playerMatchHistoryData} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestPlayerMatchHistory + * @param {number} account_id - Dota 2 account ID of the player whose match history the bot should fetch + * @param {Object} [options] - Filtering options + * @param {number} [options.start_at_match_id] - Which match ID to start searching at (pagination) + * @param {number} [options.matches_requested] - How many matches to retrieve + * @param {number} [options.hero_id] - Show only matches where player played the given hero + * @param {number} [options.request_id=account_id] - A unique identifier that identifies this request + * @param {boolean} [options.include_practice_matches] - Whether or not to include practice matches in the results + * @param {boolean} [options.include_custom_games] - Whether or not to include custom games in the results + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgDOTAGetPlayerMatchHistoryResponse` + */ Dota2.Dota2Client.prototype.requestPlayerMatchHistory = function(account_id, options, callback) { callback = callback || null; options = options || null; @@ -27,23 +43,16 @@ Dota2.Dota2Client.prototype.requestPlayerMatchHistory = function(account_id, opt onPlayerMatchHistoryResponse, callback); }; -// Dota2.Dota2Client.prototype.requestProfile = function(account_id, request_name, callback) { -// callback = callback || null; -// var _self = this; - -// /* Sends a message to the Game Coordinator requesting `accountId`'s profile data. Listen for `profileData` event for Game Coordinator's response. */ -// if (this.debug) util.log("Sending profile request"); - -// var payload = { -// "account_id": account_id, -// "request_name": request_name, -// "engine": 1 -// }; -// this.sendToGC( Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCProfileRequest, -// Dota2.schema.lookupType("CMsgDOTAProfileRequest").encode(payload).finish(), -// onProfileResponse, callback); -// }; - +/** + * Sends a message to the Game Coordinator requesting `account_id`'s profile card. + * This method is heavily rate limited. When abused, the GC just stops responding. + * Even the regular client runs into this limit when you check too many profiles. + * Provide a callback or listen for {@link module:Dota2.Dota2Client#event:profileCardData|profileCardData} event for Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestProfileCard + * @param {number} account_id - Dota 2 account ID of the player whose profile card the bot should fetch + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgDOTAProfileCard` + */ Dota2.Dota2Client.prototype.requestProfileCard = function(account_id, callback) { callback = callback || null; var _self = this; @@ -58,24 +67,15 @@ Dota2.Dota2Client.prototype.requestProfileCard = function(account_id, callback) Dota2.schema.lookupType("CMsgClientToGCGetProfileCard").encode(payload).finish(), onProfileCardResponse, callback); }; -/* -// DEPRECATED -Dota2.Dota2Client.prototype.requestPassportData = function(account_id, callback) { - callback = callback || null; - var _self = this; - - // Sends a message to the Game Coordinator requesting `accountId`'s passport data. Listen for `passportData` event for Game Coordinator's response. - if (this.debug) util.log("Sending passport data request"); - - var payload = { - "account_id": account_id - }; - this.sendToGC( Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCPassportDataRequest, - Dota2.schema.lookupType("CMsgPassportDataRequest").encode(payload).finish(), - onPassportDataResponse, callback); -}; -*/ +/** + * Sends a message to the Game Coordinator requesting the Hall of Fame data for `week`. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:hallOfFameData|hallOfFameData} event for the Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestHallOfFame + * @param {number} week - The week of which you wish to know the Hall of Fame members; will return latest week if omitted. Weeks are counted from start of unix epoch with a lower bound of 2233 (2012-10-18) + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgDOTAHallOfFameResponse` + */ Dota2.Dota2Client.prototype.requestHallOfFame = function(week, callback) { week = week || null; callback = callback || null; @@ -92,10 +92,18 @@ Dota2.Dota2Client.prototype.requestHallOfFame = function(week, callback) { onHallOfFameResponse, callback); }; +/** + * Sends a message to the Game Coordinator requesting one or multiple `account_ids` player information. + * This includes their display name, country code, team info and sponsor, fantasy role, official information lock status, and if the user is marked as a pro player. + * Listen for the {@link module:Dota2.Dota2Client#event:playerInfoData|playerInfoData} event for the Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestPlayerInfo + * @param {number|number[]} account_ids - Either a single or array of Account IDs (lower 32-bits of a 64-bit Steam ID) of desired user(s) player info. + */ Dota2.Dota2Client.prototype.requestPlayerInfo = function(account_ids) { account_ids = account_ids || []; account_ids = (Array.isArray(account_ids) ? account_ids : [account_ids]).map(id => {return {'account_id': id};}); - console.log(account_ids); + if (account_ids.length == 0) { if (this.debug) util.log("Account ids must be a single id or array of ids."); return null; @@ -111,6 +119,14 @@ Dota2.Dota2Client.prototype.requestPlayerInfo = function(account_ids) { Dota2.schema.lookupType("CMsgGCPlayerInfoRequest").encode(payload).finish()); }; +/** + * Sends a message to the Game Coordinator requesting `account_id`'s trophy data. + * Provide a callback or listen for {@link module:Dota2.Dota2Client#event:trophyListData|trophyListData} event for Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestTrophyList + * @param {number} account_id - Dota 2 account ID of the player whose trophy data the bot should fetch + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgClientToGCGetTrophyListResponse` + */ Dota2.Dota2Client.prototype.requestTrophyList = function(account_id, callback) { account_id = account_id || null; var _self = this; @@ -126,6 +142,15 @@ Dota2.Dota2Client.prototype.requestTrophyList = function(account_id, callback) { onTrophyListResponse, callback); }; +/** + * Sends a message to the Game Coordinator requesting `account_id`'s player stats. + * Provide a callback or listen for {@link module:Dota2.Dota2Client#event:playerStatsData|playerStatsData} event for Game Coordinator's response. + * This data contains all stats shown on a player's profile page. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestPlayerStats + * @param {number} account_id - Dota 2 account ID of the player whose player stats the bot should fetch + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgGCToClientPlayerStatsResponse` + */ Dota2.Dota2Client.prototype.requestPlayerStats = function(account_id, callback) { callback = callback || null; account_id = account_id || null; @@ -141,8 +166,97 @@ Dota2.Dota2Client.prototype.requestPlayerStats = function(account_id, callback) onPlayerStatsResponse, callback); } -// Handlers +// Events +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestPlayerMatchHistory|request for a player's match history} + * @event module:Dota2.Dota2Client#playerMatchHistoryData + * @param {number} requestId - Id of the request to which this event is the answer + * @param {CMsgDOTAGetPlayerMatchHistoryResponse} matchHistoryResponse - The raw response data containing the user's match history. + */ + /** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestProfileCard|request for a player's profile card} + * @event module:Dota2.Dota2Client#profileCardData + * @param {number} account_id - Dota2 account ID of the player whose profile card was fetched. + * @param {CMsgDOTAProfileCard} profileCardResponse - The raw response data containing the user's profile card. + */ + /** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestHallOfFame|request for a player's profile card} + * @event module:Dota2.Dota2Client#hallOfFameData + * @param {number} week - Weeks since unix epoch for which the hall of fame data was fetched + * @param {Object[]} featured_players - This week's featured players + * @param {number} featured_players[].account_id - Dota2 account id of the featured player + * @param {number} featured_players[].hero_id - ID of the hero + * @param {number} featured_players[].average_scaled_metric - Scaled metric of awesomeness + * @param {number} featured_players[].num_games - The number of games played + * @param {Object} featured_farmer - This week's featured farmer + * @param {number} featured_farmer.account_id - Dota2 account id of the featured farmer + * @param {number} featured_farmer.hero_id - ID of the hero + * @param {number} featured_farmer.gold_per_min - GPM for the featured match + * @param {number} featured_farmer.match_id - Match ID of the featured match + * @param {CMsgDOTAHallOfFameResponse} hallOfFameResponse - The raw response data containing the requested week's hall of fame. + */ + /** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestPlayerInfo|request for a player's info} + * @event module:Dota2.Dota2Client#playerInfoData + * @param {Object} playerInfoData - A `CMsgGCPlayerInfo` object containing the player's info. + * @param {Object[]} playerInfoData.player_infos - List of player information + * @param {number} playerInfoData.player_infos[].account_id - Dota2 account ID of the player + * @param {string} playerInfoData.player_infos[].name - The display name for the player + * @param {string} playerInfoData.player_infos[].country_code - The abbreviated country code for the user if available (i.e. `us`, `cn`, etc...) + * @param {number} playerInfoData.player_infos[].fantasy_role - The role of the player, either core or support, `1` and `2` respectively + * @param {number} playerInfoData.player_infos[].team_id - The numerical id of the user's team + * @param {string} playerInfoData.player_infos[].team_name - The name of the team the user is on, ex: `Cloud9` + * @param {string} playerInfoData.player_infos[].team_tag - The abbreviated tag of a team prepended to a player's name, ex: `C9` + * @param {string} playerInfoData.player_infos[].sponsor - The sponsor listed in the player's official info, ex: `HyperX` + * @param {boolean} playerInfoData.player_infos[].is_locked - Whether or not the user's official player info has been locked from editing, `true` or `false` + * @param {boolean} playerInfoData.player_infos[].is_pro - Whether the player is considered a pro player by Valve, `true` or `false` + * @param {number} playerInfoData.player_infos[].locked_until - Timestamp indicating end of lock period + * @param {number} playerInfoData.player_infos[].timestamp - Unknown + */ + /** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestTrophyList|request for a player's trophy list} + * @event module:Dota2.Dota2Client#trophyListData + * @param {Object} trophyListResponse - A `CMsgClientToGCGetTrophyListResponse` object containing the player's trophy list. + * @param {number} trophyListResponse.account_id - Dota2 account ID of the player + * @param {Object[]} trophyListResponse.trophies - List of player trophies + * @param {number} trophyListResponse.trophies[].trophy_id - Id of the trophy + * @param {number} trophyListResponse.trophies[].trophy_score - The score this trophy has counted. This is usually a level, but can represent other things, like number of challenges completed, or coins collected, etc... + * @param {number} trophyListResponse.trophies[].last_updated - The last time the trophy has been updated, in Unix time + * @param {string} trophyListResponse.profile_name - The name displayed on the user's dota profile page and profile card + */ + + /** + * Player statistics + * @typedef {Object} module:Dota2.schema.CMsgGCToClientPlayerStatsResponse + * @property {number} account_id - Dota2 account ID of the player + * @property {number[]} player_stats + * @property {number} match_count - Number of matches played + * @property {number} mean_gpm - Mean GPM per match over the last 20 matches + * @property {number} mean_xppm - Mean XPPM per match over the last 20 matches + * @property {number} mean_lasthits - Mean last hits per match over the last 20 matches + * @property {number} rampages - All time number of rampages + * @property {number} triple_kills - All time number of triple kills + * @property {number} first_blood_claimed - All time number of times the player claimed first blood + * @property {number} first_blood_given - All time number of times the player fed first blood + * @property {number} couriers_killed - All time number of couriers killed + * @property {number} aegises_snatched - All time number of aegises snatched + * @property {number} cheeses_eaten - All time amount of cheese eaten + * @property {number} creeps_stacked - All time number of camps stacked + * @property {number} fight_score - Fighting score over the last 20 matches + * @property {number} farm_score - Farming score over the last 20 matches + * @property {number} support_score - Support score over the last 20 matches + * @property {number} push_score - Push score over the last 20 matches + * @property {number} versatility_score - Hero versatility over the last 20 matches + */ + + /** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestPlayerStats|request for a player's stats} + * @event module:Dota2.Dota2Client#playerStatsData + * @param {number} account_id - Dota2 account ID of the player + * @param {module:Dota2.schema.CMsgGCToClientPlayerStatsResponse} playerStatsResponse -The player's stats. + */ +// Handlers var handlers = Dota2.Dota2Client.prototype._handlers; var onPlayerMatchHistoryResponse = function onPlayerMatchHistoryResponse(message, callback) { @@ -160,21 +274,6 @@ var onPlayerMatchHistoryResponse = function onPlayerMatchHistoryResponse(message }; handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgDOTAGetPlayerMatchHistoryResponse] = onPlayerMatchHistoryResponse; -var onProfileResponse = function onProfileResponse(message, callback) { - callback = callback || null; - var profileResponse = Dota2.schema.lookupType("CMsgDOTAProfileResponse").decode(message); - - if (profileResponse.result === 1) { - if (this.debug) util.log("Received profile data for: " + profileResponse.game_account_client.account_id); - this.emit("profileData", profileResponse.game_account_client.account_id, profileResponse); - if (callback) callback(null, profileResponse); - } else { - if (this.debug) util.log("Received a bad profileResponse"); - if (callback) callback(profileResponse.result, profileResponse); - } -}; -handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCProfileResponse] = onProfileResponse; - var onProfileCardResponse = function onProfileCardResponse(message, callback) { callback = callback || null; var profileCardResponse = Dota2.schema.lookupType("CMsgDOTAProfileCard").decode(message); @@ -184,18 +283,7 @@ var onProfileCardResponse = function onProfileCardResponse(message, callback) { if (callback) callback(null, profileCardResponse); }; handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgClientToGCGetProfileCardResponse] = onProfileCardResponse; -/* -// DEPRECATED -var onPassportDataResponse = function onPassportDataResponse(message, callback) { - callback = callback || null; - var passportDataResponse = Dota2.schema.lookupType("CMsgPassportDataResponse").decode(message); - if (this.debug) util.log("Received passport data for: " + passportDataResponse.account_id); - this.emit("passportData", passportDataResponse.account_id, passportDataResponse); - if (callback) callback(null, passportDataResponse); -}; -handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCPassportDataResponse] = onPassportDataResponse; -*/ var onHallOfFameResponse = function onHallOfFameResponse(message, callback) { callback = callback || null; var hallOfFameResponse = Dota2.schema.lookupType("CMsgDOTAHallOfFameResponse").decode(message); diff --git a/handlers/custom.js b/handlers/custom.js index 848d1605..33337fff 100644 --- a/handlers/custom.js +++ b/handlers/custom.js @@ -1,6 +1,12 @@ var Dota2 = require("../index"), util = require("util"); - + +/** + * Requests a list of custom game modes for which there are currently lobbies available. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestJoinableCustomGameModes + * @param {ServerRegion} [server_region=ServerRegion.UNSPECIFIED] - The server region for which you'd like to obtain the joinable custom game modes + */ Dota2.Dota2Client.prototype.requestJoinableCustomGameModes = function requestJoinableCustomGameModes(server_region) { // Request list of joinable custom games for a certain region server_region = server_region || Dota2.ServerRegion.UNSPECIFIED; @@ -13,6 +19,14 @@ Dota2.Dota2Client.prototype.requestJoinableCustomGameModes = function requestJoi Dota2.schema.lookupType("CMsgJoinableCustomGameModesRequest").encode(payload).finish()); } +// Events +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestJoinableCustomGameModes|request for joinable custom game modes}. + * @event module:Dota2.Dota2Client#joinableCustomGameModes + * @param {CMsgJoinableCustomGameModesResponseEntry[]} joinableCustomGameModes - List of joinable custom game modes + */ + +// Handlers var handlers = Dota2.Dota2Client.prototype._handlers; var onJoinableCustomGameModesResponse = function onJoinableCustomGameModesResponse(message) { diff --git a/handlers/fantasy.js b/handlers/fantasy.js index 7a093bb9..6a6fb75a 100644 --- a/handlers/fantasy.js +++ b/handlers/fantasy.js @@ -3,16 +3,24 @@ var Dota2 = require("../index"), Long = require('long'); // Methods +/** + * Player with player cards + * @typedef {Object} module:Dota2.Dota2Client#requestPlayerCardsByPlayer.FantasyPlayer + * @property {number} account_id - Dota2 account ID of the player + * @property {Object[]} cards - Player cards of this player in the bot's inventory + * @property {number} cards[].id - ID of the card + * @property {external:Long} cards[].bonuses - 64bit bitmask for the bonuses of this card + * @property {module:Dota2.schema.CMsgGCToClientPlayerStatsResponse} stats - Player stats + */ -// Returns a list of promises which resolve to a list of players, with player stats if the call to the GC was succesful. -// Maximum delay before promises resolve is ~20s. -// A player object looks like this: -// { -// 'account_id' : uint32, -// 'cards' : [{'id' : uint32, 'bonuses' : uint64}], -// 'stats' : CMsgGCToClientPlayerStatsResponse (if GC responded before 2s timeout) -// } -// For magic numbers, see -> https://raw.githubusercontent.com/SteamDatabase/GameTracking/master/dota/game/dota/pak01_dir/scripts/items/items_game.txt +/** + * Requests the player stats for each of the players for which you have one or multiple player cards. + * All requests are staggered in 200ms intervals and time out after 2s. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @async Returns a list of promises that resolve to {@link module:Dota2.Dota2Client#requestPlayerCardsByPlayer.FantasyPlayer} objects + * @alias module:Dota2.Dota2Client#requestPlayerCardsByPlayer + * @returns {FantasyPlayer[]} + */ Dota2.Dota2Client.prototype.requestPlayerCardsByPlayer = function() { if(this.Inventory) { var playercards = this.Inventory.filter(item => item.def_index == 11953); @@ -79,6 +87,15 @@ Dota2.Dota2Client.prototype.requestPlayerCardsByPlayer = function() { // onPlayerCardInfoResponse, callback); // } +/** + * Sends a message to the Game Coordinator requesting your fantasy line-up for a specific day of a given tournament. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:playerCardRoster|playerCardRoster} event for the Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestPlayerCardRoster + * @param {number} league_id - ID of the league + * @param {number} timestamp - Date in timeframe of the league + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgClientToGCGetPlayerCardRosterResponse` + */ Dota2.Dota2Client.prototype.requestPlayerCardRoster = function(league_id, timestamp, callback) { callback = callback || null; var _self = this; @@ -96,6 +113,17 @@ Dota2.Dota2Client.prototype.requestPlayerCardRoster = function(league_id, timest onGetPlayerCardRosterResponse, callback); } +/** + * Sends a message to the Game Coordinator requesting to draft a certain player card in a specific slot, for a given day in a tournament. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:playerCardDrafted|playerCardDrafted} event for the Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#draftPlayerCard + * @param {number} league_id - ID of the league for which you're drafting a player card + * @param {number} timestamp - Timestamp of the day for which you want to draft a player card + * @param {number} slot - Slot in the draft which you want to fill + * @param {number} player_card_id - Item ID of the player card you want to draft + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgClientToGCSetPlayerCardRosterResponse` + */ Dota2.Dota2Client.prototype.draftPlayerCard = function(league_id, timestamp, slot, player_card_id, callback) { callback = callback || null; var _self = this; @@ -113,6 +141,17 @@ Dota2.Dota2Client.prototype.draftPlayerCard = function(league_id, timestamp, slo onSetPlayerCardRosterResponse, callback); } +// Events +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestPlayerCardRoster|request for a player's fantasy roster} + * @event module:Dota2.Dota2Client#playerCardRoster + * @param {CMsgClientToGCGetPlayerCardRosterResponse} playerCardRoster - The raw response data containing the fantasy draft and score if available. + */ +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#draftPlayerCard|draft of a player card} + * @event module:Dota2.Dota2Client#playerCardDrafted + * @param {number} playerCardRoster - The result of the operation. See `CMsgClientToGCSetPlayerCardRosterResponse.result`. + */ // Handlers var handlers = Dota2.Dota2Client.prototype._handlers; @@ -147,6 +186,6 @@ var onSetPlayerCardRosterResponse = function onSetPlayerCardRosterResponse(messa var playerCardRoster = Dota2.schema.lookupType("CMsgClientToGCSetPlayerCardRosterResponse").decode(message); if (this.debug) util.log("Received player card draft result: "+playerCardRoster.result); this.emit("playerCardDrafted", playerCardRoster.result); - if (callback) callback(playerCardRoster.result); + if (callback) callback(playerCardRoster.result, playerCardRoster); }; handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgClientToGCSetPlayerCardRosterResponse] = onSetPlayerCardRosterResponse; \ No newline at end of file diff --git a/handlers/general.js b/handlers/general.js index 2faf2428..91e3fd33 100644 --- a/handlers/general.js +++ b/handlers/general.js @@ -1,7 +1,15 @@ var Dota2 = require("../index"), util = require("util"); - +// Events +/** + * Emitted when the server wants the client to create a pop-up + * @event module:Dota2.Dota2Client#popup + * @param {number} id - Type of the pop-up. + * @param {CMsgDOTAPopup} popup - The raw pop-up object. Can contain further specifications like formattable text + */ + + // Handlers var handlers = Dota2.Dota2Client.prototype._handlers; diff --git a/handlers/guild.js b/handlers/guild.js index b6a2c077..cc4c3953 100644 --- a/handlers/guild.js +++ b/handlers/guild.js @@ -86,7 +86,6 @@ var onGuildDataResponse = function onGuildDataResponse(message) { if (this.debug) util.log("Got guild data"); this.emit("guildData", response.guild_id, response.members, response); }; - handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCGuildData] = onGuildDataResponse; var onGuildInviteResponse = function onGuildInviteResponse(message, callback) { diff --git a/handlers/helper.js b/handlers/helper.js index 2ff1197d..e8865e7c 100644 --- a/handlers/helper.js +++ b/handlers/helper.js @@ -2,6 +2,12 @@ var Dota2 = require("../index"), util = require("util"); // Enums +/** + * Enum for all possible `EResult` values + * @alias module:Dota2.EResult + * @readonly + * @enum {number} + */ Dota2.EResult = { k_EResultOK : 1, // success k_EResultFail : 2, // generic failure @@ -59,7 +65,13 @@ Dota2.EResult = { k_EResultDiskFull : 54, k_EResultRemoteCallFailed : 55, }; - +/** + * Enum for all server regions. This enum is kept up to date on a best effort base. + * For the up-to-date values, check your game's regions.txt or {@link https://github.com/SteamDatabase/GameTracking-Dota2/blob/master/game/dota/pak01_dir/scripts/regions.txt|SteamDB's version} + * @alias module:Dota2.ServerRegion + * @readonly + * @enum {number} + */ Dota2.ServerRegion = { UNSPECIFIED : 0, USWEST : 1, @@ -84,6 +96,39 @@ Dota2.ServerRegion = { PWTELECOMWUHAN : 20 }; +/** + * Enum for different types of series. + * @alias module:Dota2.SeriesType + * @readonly + * @enum {number} + */ +Dota2.SeriesType = { + NONE: 0, + BEST_OF_THREE: 1, + BEST_OF_FIVE: 2 +}; + +/** + * Enum for different bot difficulty levels. + * @alias module:Dota2.BotDifficulty + * @readonly + * @enum {number} + */ +Dota2.BotDifficulty = { + PASSIVE: 0, + EASY: 1, + MEDIUM: 2, + HARD: 3, + UNFAIR: 4 +}; + + +/** + * @callback module:Dota2~requestCallback + * @param {number} errorCode - Null if everything went well, else the error code + * @param {Object} responseMessage - The response message the GC sent + */ + // Helper methods Dota2._parseOptions = function(options, possibleOptions) { var details, option, type, value; diff --git a/handlers/inventory.js b/handlers/inventory.js index 5202b6a7..8acd5009 100644 --- a/handlers/inventory.js +++ b/handlers/inventory.js @@ -2,24 +2,30 @@ var Dota2 = require("../index"), util = require("util"); // Methods - +/** + * Attempts to change the position of one or more items in your inventory. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#setItemPositions + * @param {Object[]} item_positions - The new positions of the items + * @param {number} item_positions[].item_id - ID of the item + * @param {number} item_positions[].position - New position of the item + */ Dota2.Dota2Client.prototype.setItemPositions = function(item_positions) { - /* Attempts to move inventory items to positions as noted itemPositions - which is interpreted as a [itemid, position] tuple. */ if (this.debug) util.log("Setting item positions."); - var payloadItemPositions = item_positions.map(function(item) { - return { - "itemId": item[0], - "position": item[1] - }; - }), - payload = { - "itemPositions": payloadItemPositions - }; + let payload = { + "itemPositions": item_positions + }; this.sendToGC( Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCSetItemPositions, Dota2.schema.lookupType("CMsgSetItemPositions").encode(payload).finish()); }; +/** + * Attempts to delete an item in your inventory. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#deleteItem + * @param {number} item_id - ID of the item + */ Dota2.Dota2Client.prototype.deleteItem = function(item_id) { /* Attempts to delete item by itemid. */ if (!this._gcReady) { diff --git a/handlers/leagues.js b/handlers/leagues.js index be3ad3d2..ddbcd881 100644 --- a/handlers/leagues.js +++ b/handlers/leagues.js @@ -2,18 +2,26 @@ var Dota2 = require("../index"), util = require("util"); // Methods - +/** + * Sends a message to the Game Coordinator requesting data on leagues being played in the given month. + * Provide a callback or listen for {@link module:Dota2.Dota2Client#event:leaguesInMonthData|leaguesInMonthData} for the Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestLeaguesInMonth + * @param {number} [month=(new Date()).getMonth()] - Month (MM) you want to query data for. **IMPORTANT NOTE**: Month is zero-aligned, not one-aligned; so Jan = 00, Feb = 01, etc. + * @param {number} [year=(new Date()).getFullYear()] - Year (YYYY) you want to query data for. + * @param {number} [tier=0] - Search only for a specific tier of tournaments. + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgDOTALeaguesInMonthResponse` + */ Dota2.Dota2Client.prototype.requestLeaguesInMonth = function(month, year, tier, callback) { - callback = callback || null; var _self = this; + var now = new Date(); // Month & year default to current time values - month = month === undefined ? (new Date()).getMonth() : month; - year = year || (new Date()).getFullYear(); + month = month === undefined ? now.getMonth() : month; + year = year || now.getFullYear(); tier = tier || 0; + callback = callback || null; - /* Sends a message to the Game Coordinator requesting the data on the given month's leagues. - Listen for `leaguesInMonthResponse` event for the Game Coordinator's response. */ if (this.debug) util.log("Sending CMsgDOTALeaguesInMonthRequest"); var payload = { @@ -26,6 +34,12 @@ Dota2.Dota2Client.prototype.requestLeaguesInMonth = function(month, year, tier, onLeaguesInMonthResponse, callback); }; +/** + * Requests info on all available official leagues from the GC. + * Listen for the {@link module:Dota2.Dota2Client#event:leagueData|leagueData} event for the Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestLeagueInfo + */ Dota2.Dota2Client.prototype.requestLeagueInfo = function() { /* Sends a message to the Game Coordinator request the info on all available official leagues */ if (this.debug) util.log("Sending CMsgRequestLeagueInfo"); @@ -36,6 +50,12 @@ Dota2.Dota2Client.prototype.requestLeagueInfo = function() { }; +/** + * Sends a message to the Game Coordinator requesting the top league matches. + * Listen for the {@link module:Dota2.Dota2Client#event:topLeagueMatchesData|topLeagueMatchesData} event for the Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestTopLeagueMatches + */ Dota2.Dota2Client.prototype.requestTopLeagueMatches = function() { /* Sends a message to the Game Coordinator request the info on all available official leagues */ if (this.debug) util.log("Sending CMsgClientToGCTopLeagueMatchesRequest"); @@ -46,8 +66,57 @@ Dota2.Dota2Client.prototype.requestTopLeagueMatches = function() { }; +// Events +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestLeaguesInMonth|request for the leagues in a given month}. + * The leagues that are returned are those which have one or more matches in the given month. + * They can however also have other matches in a different month. + * @event module:Dota2.Dota2Client#leaguesInMonthData + * @param {number} month - Month this data represents. + * @param {number} year - Year this data represents + * @param {Object[]} leagues - List of leagues that have matches in the given month + * @param {number} leagues[].league_id - ID of the league + * @param {Object[]} leagues[].schedule - The scheduled games in this league. Might contain matches in other months. + * @param {number} leagues[].schedule[].block_id - ID of the schedule block + * @param {number} leagues[].schedule[].start_time - Unix timestamp of the start time of this scheduled match + * @param {boolean} leagues[].schedule[].finals - Whether or not this is a finals game + * @param {string} leagues[].schedule[].comment - Comment about this scheduled block; often the team names & position in bracket + * @param {Object[]} leagues[].schedule[].teams - The teams duking it out in this match + * @param {number} leagues[].schedule[].teams[].team_id - ID of the team. Not every participating team seems to be hooked up to Dota 2's team system, so 0 entries can happen + * @param {string} leagues[].schedule[].teams[].name - Name of the team + * @param {external:Long} leagues[].schedule[].teams[].logo - Logo of the team + */ +/** + * Emitted when the GC sends a `CMsgDOTALiveLeagueGameUpdate`. + * @event module:Dota2.Dota2Client#liveLeagueGamesUpdate + * @param {number} live_league_games - The number of live league games + */ +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestLeagueInfo|request for league info}. + * @event module:Dota2.Dota2Client#leagueData + * @param {Object[]} leagues - List of all leagues + * @param {number} leagues[].league_id - ID of the league + * @param {number} leagues[].last_match_time - Unix timestamp of when the last match took place + * @param {number} leagues[].prize_pool_usd - Price pool in US$ + * @param {boolean} leagues[].has_live_matches - Whether or not if there are currently live matches + * @param {boolean} leagues[].is_compendium_public - Whether or not there is a public compendium + * @param {number} leagues[].compendium_version - Verion nr of the compendium + * @param {number} leagues[].compendium_content_version - Version nr of the compendium contents + */ + /** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestTopLeagueMatches|request for top league matches}. + * @event module:Dota2.Dota2Client#topLeagueMatchesData + * @param {Object[]} matches - List of top matches + * @param {external:Long} matches[].match_id - Match ID + * @param {number} matches[].start_time - Unix timestamp of the start of the match + * @param {number} matches[].duration - Duration of the match in seconds + * @param {DOTA_GameMode} matches[].game_mode - Game mode + * @param {CMsgDOTAMatchMinimal.Player} matches[].players - List of all the players in the game, contains id, hero, K/D/A and items + * @param {CMsgDOTAMatchMinimal.Tourney} matches[].tourney - Information on the league if this is a league match + * @param {EMatchOutcome} matches[].match_outcome - Who won + */ + // Handlers - var handlers = Dota2.Dota2Client.prototype._handlers; var onLeaguesInMonthResponse = function onLeaguesInMonthResponse(message, callback) { diff --git a/handlers/lobbies.js b/handlers/lobbies.js index 3bc77e09..9241ee86 100644 --- a/handlers/lobbies.js +++ b/handlers/lobbies.js @@ -1,40 +1,154 @@ var Dota2 = require("../index"), util = require("util"); -Dota2.SeriesType = { - NONE: 0, - BEST_OF_THREE: 1, - BEST_OF_FIVE: 2 -}; - Dota2._lobbyOptions = { game_name: "string", + pass_key: "string", server_region: "number", game_mode: "number", game_version: "number", cm_pick: "number", allow_cheats: "boolean", fill_with_bots: "boolean", + bot_difficulty_radiant: "number", + bot_difficulty_dire: "number", + bot_radiant: "number", + bot_dire: "number", allow_spectating: "boolean", - pass_key: "string", series_type: "number", radiant_series_wins: "number", dire_series_wins: "number", + previous_match_override: "number", allchat: "boolean", - leagueid: "number", dota_tv_delay: "number", + leagueid: "number", custom_game_mode: "string", custom_map_name: "string", custom_difficulty: "number", custom_game_id: "number", }; +/** + * @typedef {Object} module:Dota2.Dota2Client#Lobby.Options + * + * @property {string} game_name - Name of the lobby + * + * @property {string} pass_key - Lobby password + * + * @property {module:Dota2.ServerRegion} [server_region=module:Dota2.ServerRegion.UNSPECIFIED] - Server region where the lobby will be created + * + * @property {DOTA_GameMode} [game_mode=DOTA_GameMode.DOTA_GAMEMODE_AP] - Game mode + * + * @property {DOTAGameVersion} [game_version=DOTAGameVersion.GAME_VERSION_STABLE] - Version of the game + * + * @property {DOTA_CM_PICK} [cm_pick=DOTA_CM_PICK.DOTA_CM_RANDOM] - Who gets first pick + * + * @property {boolean} [allow_cheats=false] - Whether or not to allow cheats + * + * @property {boolean} [fill_with_bots=false] - Whether or not to fill empty slots with bots + * + * @property {BotDifficulty} [bot_difficulty_radiant=module:Dota2.BotDifficulty.PASSIVE] - The bot difficulty for radiant bots, if fill_with_bots is true. + * + * @property {BotDifficulty} [bot_difficulty_dire=module:Dota2.BotDifficulty.PASSIVE] - The bot difficulty for dire bots, if fill_with_bots is true. + * + * @property {number} [bot_radiant] - Presumably the ID of the custom AI to be applied to radiant bots. + * + * @property {number} [bot_dire] - Presumably the ID of the custom AI to be applied to dire bots. + * + * @property {boolean} [allow_spectating=true] - Whether or not to allow spectating + * + * @property {SeriesType} [series_type=NONE] - Whether or not the game is part of a series (Bo3, Bo5). + * + * @property {number} [radiant_series_wins=0] - # of games won so far, e.g. for a Bo3 or Bo5. + * + * @property {number} [dire_series_wins=0] - # of games won so far, e.g. for a Bo3 or Bo5. + * + * @property {number} [previous_match_override] - In a series, the match ID of the previous game. If not supplied, the GC will try + * to find it automatically based on the teams and the players. + * + * @property {boolean} [allchat=false] - Whether or not it's allowed to all-chat + * + * @property {LobbyDotaTVDelay} [dota_tv_delay=LobbyDotaTV_120] - How much time the game should be delayed for DotaTV. + * + * @property {number} [leagueid] - The league this lobby is being created for. The bot should be a league admin for this to work. + * + * @property {string} [custom_game_mode] - Name of the custom game + * + * @property {string} [custom_map_name] - Which map the custom game should be played on + * + * @property {number} [custom_difficulty] - Difficulty of the custom game + * + * @property {external:Long} [custom_game_id] - 64bit ID of the custom game mode + */ + // Methods -Dota2.Dota2Client.prototype.createPracticeLobby = function(password, options, callback) { - callback = callback || null; - this.createTournamentLobby(password, -1, -1, options, callback); - } - // callback to onPracticeLobbyResponse +/** + * Sends a message to the Game Coordinator requesting to create a lobby. + * This will automatically make the bot join the first slot on radiant team. Listen for + * {@link module:Dota2.Dota2Client#event:practiceLobbyUpdate|practiceLobbyUpdate} response for a + * snapshot-update of the newly created lobby. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * + * @alias module:Dota2.Dota2Client#createPracticeLobby + * + * @param {module:Dota2.Dota2Client#Lobby.Options} options - Configuration options for the lobby + * + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ +Dota2.Dota2Client.prototype.createPracticeLobby = function(options, callback) { + callback = callback || null; + var _self = this; + + var defaults = { + game_name: "", + server_region: Dota2.ServerRegion.UNSPECIFIED, + game_mode: Dota2.schema.lookupEnum("DOTA_GameMode").DOTA_GAMEMODE_AP, + game_version: Dota2.schema.lookupEnum("DOTAGameVersion").GAME_VERSION_STABLE, + cm_pick: Dota2.schema.lookupEnum("DOTA_CM_PICK").DOTA_CM_RANDOM, + allow_cheats: false, + fill_with_bots: false, + bot_difficulty_radiant: Dota2.BotDifficulty.PASSIVE, + bot_difficulty_dire: Dota2.BotDifficulty.PASSIVE, + allow_spectating: true, + pass_key: "", + series_type: Dota2.SeriesType.NONE, + radiant_series_wins: 0, + dire_series_wins: 0, + allchat: false, + dota_tv_delay: Dota2.schema.lookupEnum("LobbyDotaTVDelay").LobbyDotaTV_120, + leagueid: 0, + previous_match_override: 0, + custom_game_mode: "", + custom_map_name: "", + custom_difficulty: 0, + custom_game_id: 0 + }; + var finalOptions = Object.assign(defaults, options); + + if (this.debug) util.log("Sending match CMsgPracticeLobbyCreate request"); + var lobby_details = Dota2._parseOptions(finalOptions, Dota2._lobbyOptions); + var payload = { + "lobby_details": lobby_details, + "pass_key": finalOptions.pass_key + }; + + this.sendToGC( Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCPracticeLobbyCreate, + Dota2.schema.lookupType("CMsgPracticeLobbyCreate").encode(payload).finish(), + onPracticeLobbyResponse, callback); +} + +/** + * @deprecated since 5.0.0 + * @alias module:Dota2.Dota2Client#_createPracticeLobby + */ +Dota2.Dota2Client.prototype._createPracticeLobby = function(password, options, callback) { + callback = callback || null; + this.createTournamentLobby(password, -1, -1, options, callback); +} +/** + * @deprecated since 5.0.0 + * @alias module:Dota2.Dota2Client#createTournamentLobby + */ Dota2.Dota2Client.prototype.createTournamentLobby = function(password, tournament_game_id, tournament_id, options, callback) { callback = callback || null; password = password || ""; @@ -45,12 +159,13 @@ Dota2.Dota2Client.prototype.createTournamentLobby = function(password, tournamen if (this.debug) util.log("Sending match CMsgPracticeLobbyCreate request"); var lobby_details = Dota2._parseOptions(options, Dota2._lobbyOptions); lobby_details.pass_key = password; + lobby_details.leagueid = options.leagueid || tournament_id; var payload = { "lobby_details": lobby_details, "pass_key": password }; - if (tournament_game_id > 0) { + if (tournament_id > 0) { payload["tournament_game"] = true; payload["tournament_game_id"] = tournament_game_id; payload["tournament_id"] = tournament_id; @@ -60,7 +175,17 @@ Dota2.Dota2Client.prototype.createTournamentLobby = function(password, tournamen Dota2.schema.lookupType("CMsgPracticeLobbyCreate").encode(payload).finish(), onPracticeLobbyResponse, callback); }; -// callback to onPracticeLobbyResponse + +/** + * Sends a message to the Game Coordinator requesting to configure some options of the active lobby. + * Listen for {@link module:Dota2.Dota2Client#event:practiceLobbyUpdate|practiceLobbyUpdate} response + * for a snapshot-update of the newly created lobby. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#configPracticeLobby + * @param {external:Long} lobby_id - ID of the lobby + * @param {module:Dota2.Dota2Client#Lobby.Options} options - The new option values + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.configPracticeLobby = function(lobby_id, options, callback) { callback = callback || null; var _self = this; @@ -72,7 +197,14 @@ Dota2.Dota2Client.prototype.configPracticeLobby = function(lobby_id, options, ca Dota2.schema.lookupType("CMsgPracticeLobbySetDetails").encode(payload).finish(), onPracticeLobbyResponse, callback); }; -// callback to onPracticeLobbyListResponse + +/** + * Requests a lists of joinable practice lobbies. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyListData|practiceLobbyListData} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestPracticeLobbyList + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyListResponse` + */ Dota2.Dota2Client.prototype.requestPracticeLobbyList = function(callback) { callback = callback || null; var _self = this; @@ -84,7 +216,14 @@ Dota2.Dota2Client.prototype.requestPracticeLobbyList = function(callback) { Dota2.schema.lookupType("CMsgPracticeLobbyList").encode(payload).finish(), onPracticeLobbyListResponse, callback); }; -// callback to onFriendPracticeLobbyListResponse + +/** + * Requests a lists of joinable practice lobbies which have one of your friends in them. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:friendPracticeLobbyListData|friendPracticeLobbyListData} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestFriendPracticeLobbyList + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgFriendPracticeLobbyListResponse` + */ Dota2.Dota2Client.prototype.requestFriendPracticeLobbyList = function(callback) { callback = callback || null; var _self = this; @@ -96,7 +235,14 @@ Dota2.Dota2Client.prototype.requestFriendPracticeLobbyList = function(callback) Dota2.schema.lookupType("CMsgFriendPracticeLobbyListRequest").encode(payload).finish(), onFriendPracticeLobbyListResponse, callback); }; -// callback to onPracticeLobbyResponse + +/** + * Shuffles the lobby based on skill level. Requires you to be in a lobby and to be the host. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyResponse|practiceLobbyResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#balancedShuffleLobby + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.balancedShuffleLobby = function(callback) { callback = callback || null; var _self = this; @@ -109,31 +255,13 @@ Dota2.Dota2Client.prototype.balancedShuffleLobby = function(callback) { onPracticeLobbyResponse, callback); }; -//TODO: figure out the enum for team -/* -Dota2.Dota2Client.prototype.setLobbyTeamSlot = function(team, slot, callback){ - callback = callback || null; - if (!this._gcReady) { - if (this.debug) util.log("GC not ready, please listen for the 'ready' event."); - return null; - } - - if (this.debug) util.log("Sending flip teams request"); - var payload = Dota2.schema.CMsgFlipLobbyTeams.serialize({}); - - this._gc.send( - { - "msg": Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCFlipLobbyTeams, - "proto": { - "client_steam_id": this._client.steamID, - "source_app_id": this._appid - } - }, - payload.toBuffer(), - callback - ); -};*/ -// callback to onPracticeLobbyResponse +/** + * Flips the radiant and dire team players. Requires you to be in a lobby and to be the host. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyResponse|practiceLobbyResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#flipLobbyTeams + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.flipLobbyTeams = function(callback) { callback = callback || null; var _self = this; @@ -146,8 +274,15 @@ Dota2.Dota2Client.prototype.flipLobbyTeams = function(callback) { onPracticeLobbyResponse, callback); }; +/** + * Asks to invite a player to your lobby. This creates a new default lobby when you are not already in one. + * Listen for the {@link module:Dota2.Dota2Client#event:inviteCreated|inviteCreated} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#inviteToLobby + * @param {external:Long} steam_id - The Steam ID of the player you want to invite. + */ Dota2.Dota2Client.prototype.inviteToLobby = function(steam_id) { - steam_id = steam_id || null; + steam_id = steam_id.toString() || null; if (steam_id == null) { if (this.debug) util.log("Steam ID required to create a lobby invite."); return null; @@ -161,7 +296,15 @@ Dota2.Dota2Client.prototype.inviteToLobby = function(steam_id) { this.sendToGC( Dota2.schema.lookupEnum("EGCBaseMsg").k_EMsgGCInviteToLobby, Dota2.schema.lookupType("CMsgInviteToLobby").encode(payload).finish()); }; -// callback to onPracticeLobbyResponse + +/** + * Asks to kick someone from your current practice lobby. Requires you to be in a lobby and to be the host. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyResponse|practiceLobbyResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#practiceLobbyKick + * @param {number} account_id - The Dota2 account ID of the player you want to kick. + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.practiceLobbyKick = function(account_id, callback) { callback = callback || null; account_id = account_id || ""; @@ -176,7 +319,16 @@ Dota2.Dota2Client.prototype.practiceLobbyKick = function(account_id, callback) { Dota2.schema.lookupType("CMsgPracticeLobbyKick").encode(payload).finish(), onPracticeLobbyResponse, callback); }; -// callback to onPracticeLobbyResponse + +/** + * Asks to kick someone from his chosen team in your current practice lobby. + * The player will be added to the player pool + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyResponse|practiceLobbyResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#practiceLobbyKickFromTeam + * @param {number} account_id - The Dota2 account ID of the player you want to kick from his team. + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.practiceLobbyKickFromTeam = function(account_id, callback) { callback = callback || null; account_id = account_id || ""; @@ -191,7 +343,16 @@ Dota2.Dota2Client.prototype.practiceLobbyKickFromTeam = function(account_id, cal Dota2.schema.lookupType("CMsgPracticeLobbyKickFromTeam").encode(payload).finish(), onPracticeLobbyResponse, callback); }; -// callback to onPracticeLobbyJoinResponse + +/** + * Sends a message to the Game Coordinator requesting to join a lobby. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyJoinResponse|practiceLobbyJoinResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#joinPracticeLobby + * @param {externalLong} id - The ID of the lobby + * @param {number} password - The password of the lobby + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.joinPracticeLobby = function(id, password, callback) { callback = callback || null; password = password || ""; @@ -207,7 +368,14 @@ Dota2.Dota2Client.prototype.joinPracticeLobby = function(id, password, callback) Dota2.schema.lookupType("CMsgPracticeLobbyJoin").encode(payload).finish(), onPracticeLobbyJoinResponse, callback); }; -// callback to onPracticeLobbyResponse + +/** + * Sends a message to the Game Coordinator requesting to leave the current lobby. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyResponse|practiceLobbyResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#leavePracticeLobby + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.leavePracticeLobby = function(callback) { callback = callback || null; var _self = this; @@ -220,7 +388,14 @@ Dota2.Dota2Client.prototype.leavePracticeLobby = function(callback) { Dota2.schema.lookupType("CMsgPracticeLobbyLeave").encode(payload).finish(), onPracticeLobbyResponse, callback); }; -// callback to onPracticeLobbyResponse + +/** + * Abandons the current game. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyResponse|practiceLobbyResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#abandonCurrentGame + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.abandonCurrentGame = function(callback) { callback = callback || null; var _self = this; @@ -232,7 +407,15 @@ Dota2.Dota2Client.prototype.abandonCurrentGame = function(callback) { Dota2.schema.lookupType("CMsgAbandonCurrentGame").encode(payload).finish(), onPracticeLobbyResponse, callback); }; -// callback to onPracticeLobbyResponse + +/** + * Start the practice lobby. The bot will continue to receive lobby updates, but won't join the actual game. + * Requires you to be in a lobby and to be the host. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyResponse|practiceLobbyResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#launchPracticeLobby + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.launchPracticeLobby = function(callback) { callback = callback || null; var _self = this; @@ -244,7 +427,17 @@ Dota2.Dota2Client.prototype.launchPracticeLobby = function(callback) { Dota2.schema.lookupType("CMsgPracticeLobbyLaunch").encode(payload).finish(), onPracticeLobbyResponse, callback); }; -// callback to onPracticeLobbyResponse + +/** + * Sends a message to the Game Coordinator requesting to join a particular team in the lobby. + * Requires you to be in a lobby. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyResponse|practiceLobbyResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#joinPracticeLobbyTeam + * @param {number} slot - The slot you want to join + * @param {number} team - The team you want to join + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.joinPracticeLobbyTeam = function(slot, team, callback) { callback = callback || null; slot = slot ||1; @@ -262,7 +455,16 @@ Dota2.Dota2Client.prototype.joinPracticeLobbyTeam = function(slot, team, callbac Dota2.schema.lookupType("CMsgPracticeLobbySetTeamSlot").encode(payload).finish(), onPracticeLobbyResponse, callback); }; -// callback to onPracticeLobbyJoinResponse + +/** + * Sends a message to the Game Coordinator requesting to add a bot to the broadcast channel. + * Requires you to be in a lobby. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyResponse|practiceLobbyResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#joinPracticeLobbyBroadcastChannel + * @param {number} [channel=1] - The channel slot you want to fill + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.joinPracticeLobbyBroadcastChannel = function(channel, callback) { callback = callback || null; channel = channel || 1; @@ -277,7 +479,18 @@ Dota2.Dota2Client.prototype.joinPracticeLobbyBroadcastChannel = function(channel Dota2.schema.lookupType("CMsgPracticeLobbyJoinBroadcastChannel").encode(payload).finish(), onPracticeLobbyJoinResponse, callback); }; -// callback to onPracticeLobbyResponse + +/** + * Sends a message to the Game Coordinator requesting to add a bot to the given team in the lobby. + * Requires you to be in a lobby and to be the host + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyResponse|practiceLobbyResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#addBotToPracticeLobby + * @param {number} slot - The slot you want to add a bot to + * @param {number} team - The team you want to add a bot to + * @param {module:Dota2.BotDifficulty} bot_difficulty - The difficulty setting of the bot. + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgPracticeLobbyJoinResponse` + */ Dota2.Dota2Client.prototype.addBotToPracticeLobby = function(slot, team, bot_difficulty, callback) { callback = callback || null; slot = slot || 1; @@ -296,7 +509,15 @@ Dota2.Dota2Client.prototype.addBotToPracticeLobby = function(slot, team, bot_dif Dota2.schema.lookupType("CMsgPracticeLobbySetTeamSlot").encode(payload).finish(), onPracticeLobbyResponse, callback); } -// no callback + +/** + * Sends a message to the Game Coordinator confirming/denying a lobby invitation + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:practiceLobbyResponse|practiceLobbyResponse} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#respondLobbyInvite + * @param {external:Long} id - The ID of the lobby + * @param {boolean} accept - Whether or not you accept the invitation. + */ Dota2.Dota2Client.prototype.respondLobbyInvite = function(id, accept) { id = id || null; accept = accept || false; @@ -315,8 +536,45 @@ Dota2.Dota2Client.prototype.respondLobbyInvite = function(id, accept) { Dota2.schema.lookupType("CMsgLobbyInviteResponse").encode(payload).finish()); }; -// Handlers +// Events +/** + * Event that's emitted whenever the bot joins a lobby + * @event module:Dota2.Dota2Client#practiceLobbyJoinResponse + * @param {DOTAJoinLobbyResult} result - Result code + * @param {Object} response - The raw response object + * @param {DOTAJoinLobbyResult} response.result - Result code + */ +/** + * Event that's emitted in response to a {@link module:Dota2.Dota2Client#requestPracticeLobbyList|request for the list of lobbies} + * @event module:Dota2.Dota2Client#practiceLobbyListData + * @param {Object} practiceLobbyListResponse - Raw response object + * @param {boolean} practiceLobbyListResponse.tournament_games - Whether or not there are tournament games included in the list + * @param {CMsgPracticeLobbyListResponseEntry[]} practiceLobbyListResponse.lobbies - List of practice lobbies and their details + */ + /** + * Emitted when an operation changing the state of a lobby was sent to the GC and + * processed. This event only contains the acknowledgement by the GC. The actual + * update of the lobby state is communicated via {@link module:Dota2.Dota2Client#practiceLobbyUpdate} events. + * @event module:Dota2.Dota2Client#practiceLobbyResponse + * @param {DOTAJoinLobbyResult} result - Result code + * @param {Object} response - The raw response object + * @param {module:Dota2.EResult} response.result - Result code + */ +/** + * Event that's emitted in response to a {@link module:Dota2.Dota2Client#requestPracticeLobbyList|request for the list of your friends' lobbies} + * @event module:Dota2.Dota2Client#friendPracticeLobbyListData + * @param {Object} practiceLobbyListResponse - Raw response object + * @param {CMsgPracticeLobbyListResponseEntry[]} practiceLobbyListResponse.lobbies - List of practice lobbies and their details + */ + /** + * Event that's emitted whenever the bot attempts to invite someone to a lobby + * @event module:Dota2.Dota2Client#inviteCreated + * @param {external:Long} steam_id - Steam ID of the person that was invited to the lobby + * @param {external:Long} group_id - Group ID of the invitation + * @param {boolean} is_online - Whether or not the invitee is online + */ +// Handlers var handlers = Dota2.Dota2Client.prototype._handlers; var onPracticeLobbyJoinResponse = function onPracticeLobbyJoinResponse(message, callback) { @@ -340,7 +598,7 @@ var onPracticeLobbyListResponse = function onPracticeLobbyListResponse(message, var practiceLobbyListResponse = Dota2.schema.lookupType("CMsgPracticeLobbyListResponse").decode(message); if (this.debug) util.log("Received practice lobby list response " + practiceLobbyListResponse); - this.emit("practiceLobbyListData", null, practiceLobbyListResponse); + this.emit("practiceLobbyListData", practiceLobbyListResponse); if (callback) callback(null, practiceLobbyListResponse); }; handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCPracticeLobbyListResponse] = onPracticeLobbyListResponse; @@ -365,7 +623,7 @@ var onFriendPracticeLobbyListResponse = function onFriendPracticeLobbyListRespon var practiceLobbyListResponse = Dota2.schema.lookupType("CMsgFriendPracticeLobbyListResponse").decode(message); if (this.debug) util.log("Received friend practice lobby list response " + JSON.stringify(practiceLobbyListResponse)); - this.emit("friendPracticeLobbyListData", null, practiceLobbyListResponse); + this.emit("friendPracticeLobbyListData", practiceLobbyListResponse); if (callback) callback(null, practiceLobbyListResponse); }; handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCFriendPracticeLobbyListResponse] = onFriendPracticeLobbyListResponse; diff --git a/handlers/match.js b/handlers/match.js index 208710cb..564fd37c 100644 --- a/handlers/match.js +++ b/handlers/match.js @@ -9,6 +9,7 @@ Dota2._matchOptions = { matches_requested: "number", start_at_match_id: "number", min_players: "number", + request_id: "number", tournament_games_only: "boolean", account_id: "number", league_id: "number", @@ -17,12 +18,32 @@ Dota2._matchOptions = { }; // Methods +/** + * Requests a list of matches corresponding to the given criteria. The responses are paginated, + * but you can use the `start_at_match_id` and `matches_requested` options to loop through them. + * Provide a callback or listen for the {@link module:Dota2.Dota2Client#event:matchesData|matchesData} event for the GC's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestMatches + * @param {Object} [criteria] - Filtering options + * @param {number} [criteria.hero_id] - Show only matches where someone played the given hero + * @param {number} [criteria.game_mode] - Game mode + * @param {number} [criteria.start_at_match_id] - Which match ID to start searching at (pagination) + * @param {number} [criteria.matches_requested=1] - How many matches to retrieve + * @param {number} [criteria.min_players] - Minimum number of players present during the match + * @param {number} [criteria.request_id] - A unique identifier that identifies this request + * @param {boolean} [criteria.tournament_games_only] - Whether or not to only include tournament games + * @param {number} [criteria.account_id] - Dota2 account ID of a player that needs to be present in all matches + * @param {number} [criteria.league_id] - Show only matches from the league with this ID + * @param {number} [criteria.skill] - Skill level of the matches. 0 = Any, 3 = Very high skill. + * @param {number} [criteria.team_id] - Team ID of the team that's played in the matches + * @param {number} [criteria.custom_game_id] - Show only custom games with the given ID + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgDOTARequestMatchesResponse` + */ Dota2.Dota2Client.prototype.requestMatches = function(criteria, callback) { criteria = criteria || []; callback = callback || null; var _self = this; - /* Sends a message to the Game Coordinator requesting a list of matches based on the given criteria. Listen for `matchData` event for Game Coordinator's response. */ if (this.debug) util.log("Sending match request"); var payload = Dota2._parseOptions(criteria, Dota2._matchOptions); @@ -33,7 +54,16 @@ Dota2.Dota2Client.prototype.requestMatches = function(criteria, callback) { onMatchesResponse, callback); } -Dota2.Dota2Client.prototype.requestMatchDetails = function(match_id, callback) { +/** + * Sends a message to the Game Coordinator requesting the match details for the given match ID. + * This method is rate limited. When abused, the GC just stops responding. + * Provide a callback or listen for {@link module:Dota2.Dota2Client#event:matchDetailsData|matchDetailsData} event for Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestMatchDetails + * @param {number[]} match_ids - List of match ID's for which the bot should fetch the details + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgGCMatchDetailsResponse` + */ +Dota2.Dota2Client.prototype.requestMatchDetails = function(match_ids, callback) { callback = callback || null; var _self = this; @@ -41,13 +71,22 @@ Dota2.Dota2Client.prototype.requestMatchDetails = function(match_id, callback) { if (this.debug) util.log("Sending match details request"); var payload = { - "match_id": match_id + "match_id": match_ids }; this.sendToGC( Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCMatchDetailsRequest, Dota2.schema.lookupType("CMsgGCMatchDetailsRequest").encode(payload).finish(), onMatchDetailsResponse, callback); }; +/** + * Sends a message to the Game Coordinator requesting the minimal match details for the given match ID. + * This method is rate limited. When abused, the GC just stops responding. + * Provide a callback or listen for {@link module:Dota2.Dota2Client#event:matchMinimalDetailsData|matchMinimalDetailsData} event for Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestMatchMinimalDetails + * @param {number} match_id - Match ID for which the bot should fetch the minimal details + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgClientToGCMatchesMinimalResponse` + */ Dota2.Dota2Client.prototype.requestMatchMinimalDetails = function(match_ids, callback) { callback = callback || null; var _self = this; @@ -63,6 +102,12 @@ Dota2.Dota2Client.prototype.requestMatchMinimalDetails = function(match_ids, cal onMatchMinimalDetailsResponse, callback); }; +/** + * Sends a message to the Game Coordinator requesting the current match making stats. + * Listen for {@link module:Dota2.Dota2Client#event:matchmakingStatsData|matchmakingStatsData} event for Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestMatchmakingStats + */ Dota2.Dota2Client.prototype.requestMatchmakingStats = function() { /* Sends a message to the Game Coordinator requesting `match_id`'s match deails. Listen for `matchData` event for Game Coordinator's response. */ // Is not Job ID based - can't do callbacks. @@ -73,6 +118,12 @@ Dota2.Dota2Client.prototype.requestMatchmakingStats = function() { Dota2.schema.lookupType("CMsgDOTAMatchmakingStatsRequest").encode(payload).finish()); }; +/** + * Sends a message to the Game Coordinator requesting the current top matches played by your friends. + * Listen for {@link module:Dota2.Dota2Client#event:topFriendMatchesData|topFriendMatchesData} event for Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestTopFriendMatches + */ Dota2.Dota2Client.prototype.requestTopFriendMatches = function() { /* Sends a message to the Game Coordinator request the info on all available official leagues */ if (this.debug) util.log("Sending CMsgClientToGCTopFriendMatchesRequest"); @@ -83,8 +134,49 @@ Dota2.Dota2Client.prototype.requestTopFriendMatches = function() { }; -// Handlers +// Events +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestMatches|request for matches} + * @event module:Dota2.Dota2Client#matchesData + * @param {number} requestId - Id of the request to which this event is the answer + * @param {number} total_results - Total number of results corresponding to the query (max 500) + * @param {number} results_remaining - Total number of results not in this response + * @param {CMsgDOTAMatch[]} matches - List of match information objects + * @param {Object[]} series - List of series + * @param {CMsgDOTAMatch[]} series[].matches - List of match information objects for the matches in this series + * @param {number} series[].series_id - ID of the series + * @param {number} series[].series_type - Type of the series + * @param {CMsgDOTARequestMatchesResponse} matchResponse - A `CMsgDOTARequestMatchesResponse` object containing the raw response. + */ +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestMatchDetails|request for a match's details} + * @event module:Dota2.Dota2Client#matchDetailsData + * @param {number} match_id - Match ID for which the details where asked + * @param {CMsgGCMatchDetailsResponse} matchDetailsResponse - A `CMsgGCMatchDetailsResponse` object containing the raw response. + */ +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestMatchMinimalDetails|request for a/multiples match's minimal details} + * @event module:Dota2.Dota2Client#matchMinimalDetailsData + * @param {boolean} last_match - Whether or not the last of the requested matches is included in this response + * @param {CMsgClientToGCMatchesMinimalResponse} matchMinimalDetailsResponse - A `CMsgClientToGCMatchesMinimalResponse` object containing the raw response. + */ +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestMatchmakingStats|request for the match making stats} + * @event module:Dota2.Dota2Client#matchmakingStatsData + * @param {number} matchgroups_version - Version nr of the match groups (these evolve over time). For the current list check {@link https://github.com/SteamDatabase/GameTracking-Dota2/blob/master/game/dota/pak01_dir/scripts/regions.txt|regions.txt} + * @param {Object[]} match_groups - The different match groups and their stats + * @param {number} match_groups[].players_searching - The number of people searching for a match + * @param {number} match_groups[].auto_region_select_ping_penalty - Ping penalty for people searching this region + * @param {CMsgDOTAMatchmakingStatsResponse} matchmakingStatsResponse - A `CMsgDOTAMatchmakingStatsResponse` object containing the raw response. + */ +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestTopFriendMatches|request for the current top matches played by your friends} + * @event module:Dota2.Dota2Client#topFriendMatchesData + * @param {CMsgDOTAMatchMinimal[]} matches - A list of `CMsgDOTAMatchMinimal` objects containing the minimal match details of the matches your friends are currently playing. + */ + +// Handlers var handlers = Dota2.Dota2Client.prototype._handlers; var onMatchesResponse = function onMatchesResponse(message, callback) { @@ -93,6 +185,7 @@ var onMatchesResponse = function onMatchesResponse(message, callback) { if (matchResponse.total_results > 1) { if (this.debug) util.log("Received listing for matches"); this.emit("matchesData", + matchResponse.request_id, matchResponse.total_results, matchResponse.results_remaining, matchResponse.matches, @@ -141,7 +234,6 @@ var onMatchMinimalDetailsResponse = function onMatchMinimalDetailsResponse(messa }; handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgClientToGCMatchesMinimalResponse] = onMatchMinimalDetailsResponse; -// TODO: replace first two parameters by matchmakingStatsResponse.match_groups var onMatchmakingStatsResponse = function onMatchmakingStatsResponse(message) { // Is not Job ID based - can't do callbacks. var matchmakingStatsResponse = Dota2.schema.lookupType("CMsgDOTAMatchmakingStatsResponse").decode(message); diff --git a/handlers/parties.js b/handlers/parties.js index 5bbbf96e..6cd9cf24 100644 --- a/handlers/parties.js +++ b/handlers/parties.js @@ -2,6 +2,14 @@ var Dota2 = require("../index"), util = require("util"); // Methods +/** + * Responds to a party invite. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#respondPartyInvite + * @param {external:Long} id - The party's ID + * @param {boolean} [accept=false] - Whether or not you accept the invite + * @param {CMsgClientPingData} [ping_data=undefined] - Optional argument that can be provided when accepting an invite. Contains a.o. the ping to the different servers. + */ Dota2.Dota2Client.prototype.respondPartyInvite = function(id, accept, ping_data) { id = id || null; accept = accept || false; @@ -11,7 +19,7 @@ Dota2.Dota2Client.prototype.respondPartyInvite = function(id, accept, ping_data) } if (this.debug) util.log("Responding to party invite " + id + ", accept: " + accept); - // todo: set client version here? + var payload = { "party_id": id, "accept": accept, @@ -21,6 +29,11 @@ Dota2.Dota2Client.prototype.respondPartyInvite = function(id, accept, ping_data) Dota2.schema.lookupType("CMsgPartyInviteResponse").encode(payload).finish()); }; +/** + * Leaves the current party. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#leaveParty + */ Dota2.Dota2Client.prototype.leaveParty = function() { if (this.debug) util.log("Leaving party."); @@ -30,6 +43,14 @@ Dota2.Dota2Client.prototype.leaveParty = function() { Dota2.schema.lookupType("CMsgLeaveParty").encode(payload).finish()); }; +/** + * Tries to assign a party member as party leader. + * Only works if you are a party leader and the proposed user is a member of + * the current party. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#setPartyLeader + * @param {external:Long} steam_id - The Steam ID of the new party leader + */ Dota2.Dota2Client.prototype.setPartyLeader = function(steam_id) { steam_id = steam_id || null; if (this.Party == null) { @@ -50,6 +71,12 @@ Dota2.Dota2Client.prototype.setPartyLeader = function(steam_id) { Dota2.schema.lookupType("CMsgDOTASetGroupLeader").encode(payload).finish()); } +/** + * Announces whether or not you want to be coach of the current party. GC will take action accordingly. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#setPartyCoach + * @param {boolean} coach - True if you want to be coach, false if you no longer want to be coach + */ Dota2.Dota2Client.prototype.setPartyCoach = function(coach) { coach = coach || false; if (this.Party == null) { @@ -66,6 +93,12 @@ Dota2.Dota2Client.prototype.setPartyCoach = function(coach) { Dota2.schema.lookupType("CMsgDOTAPartyMemberSetCoach").encode(payload).finish()); }; +/** + * Invite a player to your party. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#inviteToParty + * @param {external:Long} steam_id - Steam ID of the player you want to invite + */ Dota2.Dota2Client.prototype.inviteToParty = function(steam_id) { steam_id = steam_id || null; if (steam_id == null) { @@ -74,7 +107,7 @@ Dota2.Dota2Client.prototype.inviteToParty = function(steam_id) { } if (this.debug) util.log("Inviting " + steam_id + " to a party."); - // todo: set client version here? + var payload = { "steam_id": steam_id }; @@ -82,6 +115,12 @@ Dota2.Dota2Client.prototype.inviteToParty = function(steam_id) { Dota2.schema.lookupType("CMsgInviteToParty").encode(payload).finish()); }; +/** + * Kick a player from your party. Only works if you're party leader. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#kickFromParty + * @param {external:Long} steam_id - Steam ID of the player you want to kick + */ Dota2.Dota2Client.prototype.kickFromParty = function(steam_id) { steam_id = steam_id || null; if (steam_id == null) { @@ -90,7 +129,7 @@ Dota2.Dota2Client.prototype.kickFromParty = function(steam_id) { } if (this.debug) util.log("Kicking " + steam_id + " from the party."); - // todo: set client version here? + var payload = { "steam_id": steam_id }; diff --git a/handlers/sourcetv.js b/handlers/sourcetv.js index a2218c15..60310196 100644 --- a/handlers/sourcetv.js +++ b/handlers/sourcetv.js @@ -2,8 +2,18 @@ var Dota2 = require("../index"), merge = require("merge"), util = require("util"); -// Methods +// Methods +/** + * Requests a list of SourceTV games based on the given criteria. + * Listen for {@link module:Dota2.Dota2Client#event:sourceTVGamesData|sourceTVGamesData} for results + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestSourceTVGames + * @param {CSourceTVGameSmall} filter_options - Filter options. Check the protobuf for a full list. + * @param {number} filter_options.league_id - ID of a league + * @param {number} filter_options.hero_id - ID of a hero that must be present in the game + * @param {number} filter_options.start_game - Number of pages sent, only values in [0, 10, 20, ... 90] are valid, and yield [1,2,3 ... 10] responses + */ Dota2.Dota2Client.prototype.requestSourceTVGames = function(filter_options) { // Unfortunately this does not seem to support callbacks filter_options = filter_options || null; @@ -23,8 +33,14 @@ Dota2.Dota2Client.prototype.requestSourceTVGames = function(filter_options) { Dota2.schema.lookupType("CMsgClientToGCFindTopSourceTVGames").encode(payload).finish()); }; +// Events +/** + * sourceTVGamesData event + * @event module:Dota2.Dota2Client#sourceTVGamesData + * @param {CMsgGCToClientFindTopSourceTVGamesResponse} sourceTVGamesResponse - The raw response data or null if a bad response was received + */ + // Handlers - var handlers = Dota2.Dota2Client.prototype._handlers; var onSourceTVGamesResponse = function onSourceTVGamesResponse(message) { @@ -52,4 +68,5 @@ var onSourceTVGamesResponse = function onSourceTVGamesResponse(message) { */ } }; -handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCToClientFindTopSourceTVGamesResponse] = onSourceTVGamesResponse; \ No newline at end of file +handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCToClientFindTopSourceTVGamesResponse] = onSourceTVGamesResponse; + diff --git a/handlers/team.js b/handlers/team.js index f20db306..70e71233 100644 --- a/handlers/team.js +++ b/handlers/team.js @@ -1,6 +1,13 @@ var Dota2 = require("../index"), util = require("util"); +/** + * Sends a message to the Game Coordinator requesting the authenticated user's team data. + * Provide a callback or listen for {@link module:Dota2.Dota2Client#event:teamData|teamData} for the Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * @alias module:Dota2.Dota2Client#requestMyTeams + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgDOTATeamsInfo` + */ Dota2.Dota2Client.prototype.requestMyTeams = function requestMyTeams(callback) { // Request the team data for the currently logged in user callback = callback || null; @@ -16,52 +23,18 @@ Dota2.Dota2Client.prototype.requestMyTeams = function requestMyTeams(callback) { Dota2.schema.lookupType("CMsgDOTAMyTeamInfoRequest").encode(payload).finish(), onTeamDataResponse, callback); } -/* -// DEPRECATED -Dota2.Dota2Client.prototype.requestTeamProfile = function requestTeamProfile(team_id, callback) { - // Request the profile of a given team - callback = callback || null; - var _self = this; - - if (this.debug) util.log("Sending team profile request"); - var payload = { - "team_id": team_id - }; - this.sendToGC( Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCTeamProfileRequest, - Dota2.schema.lookupType("CMsgDOTATeamProfileRequest").encode(payload).finish(), - onTeamProfileResponse, callback); -} -// DEPRECATED -Dota2.Dota2Client.prototype.requestTeamIDByName = function requestTeamIDByName(team_name, callback) { - // Request the ID of a given team - callback = callback || null; - var _self = this; - - if (this.debug) util.log("Sending team ID by name request"); - var payload = { - "name": team_name - }; - this.sendToGC( Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCTeamIDByNameRequest, - Dota2.schema.lookupType("CMsgDOTATeamIDByNameRequest").encode(payload).finish(), - onTeamIDByNameResponse, callback); -} -// DEPRECATED -Dota2.Dota2Client.prototype.requestTeamMemberProfile = function requestTeamMemberProfile(steam_id, callback) { - // Request the profile of a given team member - callback = callback || null; - var _self = this; - if (this.debug) util.log("Sending team member profile request"); - var payload = { - "steam_id": steam_id - }; - this.sendToGC( Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCTeamMemberProfileRequest, - Dota2.schema.lookupType("CMsgDOTATeamMemberProfileRequest").encode(payload).finish(), - onTeamProfileResponse, callback); -} -*/ - -// No longer gets a response from the GC +/** + * Sends a message to the Game Coordinator requesting The list of pro teams. + * Provide a callback or listen for {@link module:Dota2.Dota2Client#event:proTeamListData|proTeamListData} for the Game Coordinator's response. + * Requires the GC to be {@link module:Dota2.Dota2Client#event:ready|ready}. + * + * This function hasn't been responded to by the GC for a long time. + * @deprecated + * @ignore + * @alias module:Dota2.Dota2Client#requestProTeamList + * @param {module:Dota2~requestCallback} [callback] - Called with `err, CMsgDOTAProTeamListResponse` + */ Dota2.Dota2Client.prototype.requestProTeamList = function requestProTeamList(callback) { // Request the list of pro teams callback = callback || null; @@ -74,7 +47,28 @@ Dota2.Dota2Client.prototype.requestProTeamList = function requestProTeamList(cal onProTeamListResponse, callback); } +// Events +/** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestMyTeams|request for your teams}. + * @event module:Dota2.Dota2Client#teamData + * @param {CMsgDOTATeamInfo[]} teams - A list of `CMsgDOTATeamInfo` objects containing information about the teams you're in (name, members, stats, ...) + * @param {number} league_id - No clue why this is here, nor what it signifies + */ + /** + * Emitted in response to a {@link module:Dota2.Dota2Client#requestProTeamList|request for pro teams}. + * @deprecated + * @ignore + * @event module:Dota2.Dota2Client#proTeamListData + * @param {Object[]} teams - A list pro teams + * @param {number} teams[].team_id - ID of the team + * @param {string} teams[].tag - Tag of the team + * @param {number} teams[].time_created - Unix timestamp of the moment the team was created + * @param {external:Long} teams[].logo - Logo of the team + * @param {string} teams[].country_code - Two-letter country code for the team + * @param {number} teams[].member_count - Number of members in the team + */ +// Handlers var handlers = Dota2.Dota2Client.prototype._handlers; var onTeamDataResponse = function onTeamDataResponse(message, callback) { @@ -86,36 +80,6 @@ var onTeamDataResponse = function onTeamDataResponse(message, callback) { }; handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCToClientTeamsInfo] = onTeamDataResponse; -/* -// DEPRECATED -var onTeamProfileResponse = function onTeamProfileResponse(message, callback) { - var teamProfileResponse = Dota2.schema.lookupType("CMsgDOTATeamProfileResponse").decode(message); - - if (teamProfileResponse.eresult === 1) { - if (this.debug) util.log("Received team profile response " + JSON.stringify(teamProfileResponse)); - this.emit("teamProfile", teamProfileResponse.team.team_id, teamProfileResponse.team); - if (callback) callback(null, teamProfileResponse); - } else { - if (this.debug) util.log("Couldn't find team profile " + JSON.stringify(teamProfileResponse)); - if (callback) callback(teamProfileResponse.eresult, teamProfileResponse); - } -}; -handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCTeamProfileResponse] = onTeamProfileResponse; -// DEPRECATED -var onTeamIDByNameResponse = function onTeamIDByNameResponse(message, callback) { - var teamID = Dota2.schema.lookupType("CMsgDOTATeamIDByNameResponse").decode(message); - - if (teamID.eresult === 1) { - if (this.debug) util.log("Received team ID " + teamID.team_id); - this.emit("teamID", teamID.team_id); - if (callback) callback(null, teamID); - } else { - if (this.debug) util.log("Couldn't find team ID " + JSON.stringify(teamID)); - this.emit("teamID", null); - if (callback) callback(teamID.eresult, teamID); - } -}; -handlers[Dota2.schema.lookupEnum("EDOTAGCMsg").k_EMsgGCTeamIDByNameResponse] = onTeamIDByNameResponse;*/ // No longer gets triggered var onProTeamListResponse = function onProTeamListResponse(message, callback) { diff --git a/index.js b/index.js index 8a3d8036..6fad50f0 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,15 @@ +/** + * Dota 2 module + * @module Dota2 + */ + +/** + * A Long class for representing a 64 bit two's-complement integer value + * derived from the Closure Library for stand-alone use and extended with unsigned support. + * @external Long + * @see {@link https://www.npmjs.com/package/long|long} npm package + */ + var steam = require("steam"); const DOTA_APP_ID = 570; @@ -6,27 +18,111 @@ var EventEmitter = require('events').EventEmitter, fs = require("fs"), path = require("path"), util = require("util"), - bignumber = require("bignumber.js"), + Long = require("long"), Protobuf = require('protobufjs'), Dota2 = exports; Protobuf.parse.defaults.keepCase = true; var folder = fs.readdirSync(__dirname + '/proto'); + +/** + * Protobuf schema. See {@link http://dcode.io/protobuf.js/Root.html|Protobufjs#Root}. + * This object can be used to obtain special protobuf types. + * Object types can be created by `Dota2.schema.lookupType("TypeName").encode(payload :Object).finish();`. + * Enum types can be referenced by `Dota2.schema.lookupEnum("EnumName")`, which returns an object array representing the enum. + * @alias module:Dota2.schema + */ Dota2.schema = Protobuf.loadSync(folder.map(filename => __dirname + '/proto/' + filename)); -var Dota2Client = function Dota2Client(steamClient, debug, debugMore) { +/** + * The Dota 2 client that communicates with the GC + * @class + * @alias module:Dota2.Dota2Client + * @param {Object} steamClient - Node-steam client instance + * @param {boolean} debug - Print debug information to console + * @param {boolean} debugMore - Print even more debug information to console + * @extends {EventEmitter} EventEmitter + * @fires module:Dota2.Dota2Client#event:ready + * @fires module:Dota2.Dota2Client#event:unhandled + * @fires module:Dota2.Dota2Client#event:hellotimeout + * @fires module:Dota2.Dota2Client#event:popup + * @fires module:Dota2.Dota2Client#event:sourceTVGamesData + * @fires module:Dota2.Dota2Client#event:inventoryUpdate + * @fires module:Dota2.Dota2Client#event:practiceLobbyUpdate + * @fires module:Dota2.Dota2Client#event:practiceLobbyCleared + * @fires module:Dota2.Dota2Client#event:lobbyInviteUpdate + * @fires module:Dota2.Dota2Client#event:lobbyInviteCleared + * @fires module:Dota2.Dota2Client#event:practiceLobbyJoinResponse + * @fires module:Dota2.Dota2Client#event:practiceLobbyListData + * @fires module:Dota2.Dota2Client#event:practiceLobbyResponse + * @fires module:Dota2.Dota2Client#event:friendPracticeLobbyListData + * @fires module:Dota2.Dota2Client#event:inviteCreated + * @fires module:Dota2.Dota2Client#event:partyUpdate + * @fires module:Dota2.Dota2Client#event:partyCleared + * @fires module:Dota2.Dota2Client#event:partyInviteUpdate + * @fires module:Dota2.Dota2Client#event:partyInviteCleared + * @fires module:Dota2.Dota2Client#event:joinableCustomGameModes + * @fires module:Dota2.Dota2Client#event:chatChannelsData + * @fires module:Dota2.Dota2Client#event:chatJoin + * @fires module:Dota2.Dota2Client#event:chatJoined + * @fires module:Dota2.Dota2Client#event:chatLeave + * @fires module:Dota2.Dota2Client#event:chatMessage + * @fires module:Dota2.Dota2Client#event:profileCardData + * @fires module:Dota2.Dota2Client#event:playerMatchHistoryData + * @fires module:Dota2.Dota2Client#event:playerInfoData + * @fires module:Dota2.Dota2Client#event:playerStatsData + * @fires module:Dota2.Dota2Client#event:trophyListData + * @fires module:Dota2.Dota2Client#event:hallOfFameData + * @fires module:Dota2.Dota2Client#event:playerCardRoster + * @fires module:Dota2.Dota2Client#event:playerCardDrafted + * @fires module:Dota2.Dota2Client#event:leaguesInMonthData + * @fires module:Dota2.Dota2Client#event:liveLeagueGamesUpdate + * @fires module:Dota2.Dota2Client#event:leagueData + * @fires module:Dota2.Dota2Client#event:topLeagueMatchesData + * @fires module:Dota2.Dota2Client#event:teamData + * @fires module:Dota2.Dota2Client#event:matchesData + * @fires module:Dota2.Dota2Client#event:matchDetailsData + * @fires module:Dota2.Dota2Client#event:matchMinimalDetailsData + * @fires module:Dota2.Dota2Client#event:matchmakingStatsData + * @fires module:Dota2.Dota2Client#event:topFriendMatchesData + */ +Dota2.Dota2Client = function Dota2Client(steamClient, debug, debugMore) { EventEmitter.call(this); - this.debug = debug || false; this.debugMore = debugMore || false; + + /** The current state of the bot's inventory. Contains cosmetics, player cards, ... + * @type {CSOEconItem[]} + */ + this.Inventory = []; + /** The chat channels the bot has joined + * @type {CMsgDOTAJoinChatChannelResponse[]} + */ + this.chatChannels = []; // Map channel names to channel data. + /** The lobby the bot is currently in. Falsy if the bot isn't in a lobby. + * @type {CSODOTALobby} + */ + this.Lobby = null; + /** The currently active lobby invitation. Falsy if the bot has not been invited. + * @type {CSODOTALobbyInvite} + */ + this.LobbyInvite = null; + /** The party the bot is currently in. Falsy if the bot isn't in a party. + * @type {CSODOTAParty} + */ + this.Party = null; + /** The currently active party invitation. Falsy if the bot has not been invited. + * @type {CSODOTAPartyInvite} + */ + this.PartyInvite = null; var steamUser = new steam.SteamUser(steamClient); this._user = steamUser; this._client = steamClient; this._gc = new steam.SteamGameCoordinator(steamClient, DOTA_APP_ID); this._appid = DOTA_APP_ID; - this.chatChannels = []; // Map channel names to channel data. + this._gcReady = false; this._gcClientHelloIntervalId = null; this._gcConnectionStatus = Dota2.schema.lookupEnum("GCConnectionStatus").GCConnectionStatus_NO_SESSION; @@ -54,7 +150,7 @@ var Dota2Client = function Dota2Client(steamClient, debug, debugMore) { self._handlers[kMsg].call(self, body); } } else { - self.emit("unhandled", kMsg); + self.emit("unhandled", kMsg, Dota2._getMessageName(kMsg)); } }); @@ -91,19 +187,32 @@ var Dota2Client = function Dota2Client(steamClient, debug, debugMore) { self._gcClientHelloCount++; }; }; -util.inherits(Dota2Client, EventEmitter); +util.inherits(Dota2.Dota2Client, EventEmitter); -// Expose enums -Dota2Client.prototype.ServerRegion = Dota2.ServerRegion; -Dota2Client.prototype.ToAccountID = function(accid) { - return new bignumber(accid).minus('76561197960265728') - 0; +// Methods +/** + * Converts a 64bit Steam ID to a Dota2 account ID by deleting the 32 most significant bits + * @alias module:Dota2.Dota2Client.ToAccountID + * @param {string} steamID - String representation of a 64bit Steam ID + * @returns {number} Dota2 account ID corresponding with steamID + */ +Dota2.Dota2Client.prototype.ToAccountID = function(steamID) { + return new Long.fromString(steamID).sub('76561197960265728').toNumber(); }; -Dota2Client.prototype.ToSteamID = function(accid) { - return new bignumber(accid).plus('76561197960265728') + ""; +/** + * Converts a Dota2 account ID to a 64bit Steam ID + * @alias module:Dota2.Dota2Client.ToSteamID + * @param {string} accid - String representation of a Dota 2 account ID + * @returns {external:Long} 64bit Steam ID corresponding to the given Dota 2 account ID + */ +Dota2.Dota2Client.prototype.ToSteamID = function(accid) { + return new Long.fromString(accid).add('76561197960265728'); }; - -// Methods -Dota2Client.prototype.launch = function() { +/** + * Reports to Steam that you're playing Dota 2, and then initiates communication with the Game Coordinator. + * @alias module:Dota2.Dota2Client#launch + */ +Dota2.Dota2Client.prototype.launch = function() { /* Reports to Steam that we are running Dota 2. Initiates communication with GC with EMsgGCClientHello */ if (this.debug) util.log("Launching Dota 2"); this.AccountID = this.ToAccountID(this._client.steamID); @@ -125,8 +234,11 @@ Dota2Client.prototype.launch = function() { //Also immediately send clienthello setTimeout(this._sendClientHello, 1000); }; - -Dota2Client.prototype.exit = function() { +/** + * Stop sending a heartbeat to the GC and report to steam you're no longer playing Dota 2 + * @alias module:Dota2.Dota2Client#exit + */ +Dota2.Dota2Client.prototype.exit = function() { /* Reports to Steam we are not running any apps. */ if (this.debug) util.log("Exiting Dota 2"); @@ -140,7 +252,7 @@ Dota2Client.prototype.exit = function() { if (this._client.loggedOn) this._user.gamesPlayed([]); }; -Dota2Client.prototype.sendToGC = function(type, payload, handler, callback) { +Dota2.Dota2Client.prototype.sendToGC = function(type, payload, handler, callback) { var self = this; if (!this._gcReady) { if (this.debug) util.log("GC not ready, please listen for the 'ready' event."); @@ -154,10 +266,26 @@ Dota2Client.prototype.sendToGC = function(type, payload, handler, callback) { ); } +// Events +/** + * Emitted when the connection with the GC has been established + * and the client is ready to take requests. + * @event module:Dota2.Dota2Client#ready + */ +/** + * Emitted when the GC sends a message that isn't yet treated by the library. + * @event module:Dota2.Dota2Client#unhandled + * @param {number} kMsg - Proto message type ID + * @param {string} kMsg_name - Proto message type name + */ +/** + * Emitted when the connection with the GC takes longer than 30s + * @event module:Dota2.Dota2Client#hellotimeout + */ // Handlers -var handlers = Dota2Client.prototype._handlers = {}; +var handlers = Dota2.Dota2Client.prototype._handlers = {}; handlers[Dota2.schema.lookupEnum("EGCBaseClientMsg").k_EMsgGCClientWelcome] = function clientWelcomeHandler(message) { /* Response to our k_EMsgGCClientHello, now we can execute other GC commands. */ @@ -209,7 +337,6 @@ handlers[Dota2.schema.lookupEnum("EGCBaseClientMsg").k_EMsgGCClientConnectionSta } }; -Dota2.Dota2Client = Dota2Client; require("./handlers/cache"); require("./handlers/inventory"); diff --git a/package.json b/package.json index ff52d4be..bcb0c88e 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "dota2", - "version": "4.2.1", + "version": "5.0.0", "dependencies": { - "bignumber.js": "^3.0.0", + "long": "^3.0.0", "deferred": "^0.7.2", "merge": "^1.2.0", "protobufjs": "^6.0.0", diff --git a/proto/dota_gcmessages_client.proto b/proto/dota_gcmessages_client.proto index 5fc2de3b..7c25002f 100644 --- a/proto/dota_gcmessages_client.proto +++ b/proto/dota_gcmessages_client.proto @@ -881,7 +881,22 @@ message CMsgDOTAGetEventPointsResponse { optional uint32 account_id = 7; optional bool owned = 8; optional uint32 audit_action = 9; - optional uint32 periodic_points_remaining = 10; +} + +message CMsgDOTAGetPeriodicResource { + optional uint32 account_id = 1; + optional uint32 periodic_resource_id = 2; + optional uint32 timestamp = 3; +} + +message CMsgDOTAGetPeriodicResourceResponse { + optional uint32 periodic_resource_max = 1; + optional uint32 periodic_resource_used = 2; +} + +message CMsgDOTAPeriodicResourceUpdated { + optional .CMsgDOTAGetPeriodicResource periodic_resource_key = 1; + optional .CMsgDOTAGetPeriodicResourceResponse periodic_resource_value = 2; } message CMsgDOTALiveLeagueGameUpdate { @@ -1668,8 +1683,9 @@ message CMsgClientToGCRequestEventPointLogResponse { optional uint32 recipe_item_def_index = 1; } - message AchievementEvent { + message ActionRewardEvent { optional uint32 action_id = 1; + optional uint32 action_score = 2; } message MysteryItemReceivedEvent { @@ -1707,14 +1723,11 @@ message CMsgClientToGCRequestEventPointLogResponse { optional .CMsgClientToGCRequestEventPointLogResponse.TipGivenEvent tip_given_event = 8; optional .CMsgClientToGCRequestEventPointLogResponse.TipReceivedEvent tip_received_event = 9; optional .CMsgClientToGCRequestEventPointLogResponse.RecycledItemEvent recycled_item_event = 10; - optional .CMsgClientToGCRequestEventPointLogResponse.AchievementEvent achievement_event = 11; + optional .CMsgClientToGCRequestEventPointLogResponse.ActionRewardEvent action_reward_event = 11; optional .CMsgClientToGCRequestEventPointLogResponse.InGamePredictionCorrectEvent in_game_prediction_event = 12; optional .CMsgClientToGCRequestEventPointLogResponse.CorrectPredictionEvent prediction_event = 13; - optional .CMsgClientToGCRequestEventPointLogResponse.WeekendTourneyPayoutEvent weekend_tourney_payout_event = 14; optional .CMsgClientToGCRequestEventPointLogResponse.FantasyRewardEvent fantasy_reward_event = 15; optional .CMsgClientToGCRequestEventPointLogResponse.BracketRewardEvent bracket_reward_event = 16; - optional bool weekly_quest_completed_event = 17; - optional bool daily_quest_completed_event = 18; } optional bool result = 1; diff --git a/proto/dota_gcmessages_client_chat.proto b/proto/dota_gcmessages_client_chat.proto index 6e7f4ebb..d7543d18 100644 --- a/proto/dota_gcmessages_client_chat.proto +++ b/proto/dota_gcmessages_client_chat.proto @@ -117,6 +117,7 @@ message CMsgDOTAChatMessage { optional uint32 badge_level = 25; optional uint32 suggest_pick_hero_id = 26; optional string suggest_pick_hero_role = 27; + optional uint32 suggest_ban_hero_id = 30; optional bool terse = 28; } diff --git a/proto/dota_gcmessages_msgid.proto b/proto/dota_gcmessages_msgid.proto index 327a7036..5a9f95fe 100644 --- a/proto/dota_gcmessages_msgid.proto +++ b/proto/dota_gcmessages_msgid.proto @@ -688,5 +688,9 @@ enum EDOTAGCMsg { k_EMsgGCIsProResponse = 8208; k_EMsgDOTAClaimEventAction = 8209; k_EMsgDOTAClaimEventActionResponse = 8210; + k_EMsgDOTAGetPeriodicResource = 8211; + k_EMsgDOTAGetPeriodicResourceResponse = 8212; + k_EMsgDOTAPeriodicResourceUpdated = 8213; + k_EMsgServerToGCSpendWager = 8214; } diff --git a/proto/dota_shared_enums.proto b/proto/dota_shared_enums.proto index eb82c971..fa234f1b 100644 --- a/proto/dota_shared_enums.proto +++ b/proto/dota_shared_enums.proto @@ -70,7 +70,8 @@ enum EEvent { EVENT_ID_FALL_MAJOR_2016 = 15; EVENT_ID_WINTER_MAJOR_2017 = 16; EVENT_ID_NEW_BLOOM_2017 = 17; - EVENT_ID_COUNT = 18; + EVENT_ID_INTERNATIONAL_2017 = 18; + EVENT_ID_COUNT = 19; } enum DOTALeaverStatus_t { diff --git a/proto/econ_gcmessages.proto b/proto/econ_gcmessages.proto index 45875b6c..0f950051 100644 --- a/proto/econ_gcmessages.proto +++ b/proto/econ_gcmessages.proto @@ -305,6 +305,7 @@ message CMsgGCToGCGetUserSessionServer { message CMsgGCToGCGetUserSessionServerResponse { optional fixed64 server_steam_id = 1; + optional bool is_online = 2; } message CMsgGCToGCGetUserServerMembers { diff --git a/test/test.js b/test/test.js index f059b21a..84e6d56d 100644 --- a/test/test.js +++ b/test/test.js @@ -138,6 +138,10 @@ var steam = require("steam"), describe('#ToSteamID', function () { it('should convert a 32-bit account ID into a 64-bit Steam ID ', convertAccountIDToSteamID); }); + + describe('#ToMsgID', function () { + it('should convert a Msg ID to its name ', invertKMsgTypeID); + }); }); describe('Inventory', function () { @@ -179,23 +183,23 @@ var steam = require("steam"), }); }); - describe('Guild', function () { - describe('#requestGuildData', function () { - it('should return a list of guid IDs and a list of any open parties they have'); // TODO - }); - - describe('#inviteToGuild', function () { - it('should invite an account to join a guild'); // TODO - }); - - describe('#cancelInviteToGuild', function () { - it('should cancel a pending guild invitation'); // TODO - }); - - describe('#setGuildAccountRole', function () { - it('should set a given account\'s role within a guild'); // TODO - }); - }); + // describe('Guild', function () { + // describe('#requestGuildData', function () { + // it('should return a list of guid IDs and a list of any open parties they have'); // TODO + // }); + + // describe('#inviteToGuild', function () { + // it('should invite an account to join a guild'); // TODO + // }); + + // describe('#cancelInviteToGuild', function () { + // it('should cancel a pending guild invitation'); // TODO + // }); + + // describe('#setGuildAccountRole', function () { + // it('should set a given account\'s role within a guild'); // TODO + // }); + // }); describe('Community', function () { describe('#requestPlayerMatchHistory', function () { @@ -323,16 +327,24 @@ var steam = require("steam"), describe('Lobbies', function () { describe('#joinPracticeLobby', function () { - it('should join a lobby with the given id'); // TODO + it('should join a lobby with the given id'); //TODO }); describe('#createPracticeLobby', function () { - it('should create a lobby'); // TODO + it('should create a lobby', function (done) { + Dota2.createPracticeLobby({ + "game_name": "node-dota2 test", + "server_region": dota2.ServerRegion.EUROPE, + "pass_key": "IShouldNotJoinThisBecauseItWillSoonBeGone" + } , function (err, response) { + done(err); + }); + }); }); - describe('#createTournamentLobby', function () { - it('should create a tournament lobby'); // TODO - }); + // describe('#createTournamentLobby', function () { + // it('should create a tournament lobby'); // TODO + // }); describe('#balancedShuffleLobby', function () { it('should shuffle the teams within the lobby'); // TODO @@ -359,7 +371,11 @@ var steam = require("steam"), }); describe('#leavePracticeLobby', function () { - it('should leave a lobby'); // TODO + it('should leave a lobby', function (done) { + Dota2.leavePracticeLobby(function (err, response) { + done(err); + }); + }); }); describe('#requestPracticeLobbyList', function () {