{"id":13693246,"url":"https://github.com/andrewzah/dotacr","last_synced_at":"2025-05-02T21:31:47.876Z","repository":{"id":105900813,"uuid":"73417088","full_name":"andrewzah/dotacr","owner":"andrewzah","description":"Mirror of https://git.andrewzah.com/andrei/dotacr","archived":false,"fork":false,"pushed_at":"2018-02-25T01:22:28.000Z","size":168,"stargazers_count":9,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-26T09:02:13.062Z","etag":null,"topics":["crystal","dota","steam-api","wrapper"],"latest_commit_sha":null,"homepage":"","language":"Crystal","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andrewzah.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-11-10T20:08:10.000Z","updated_at":"2018-06-21T15:23:00.000Z","dependencies_parsed_at":"2024-01-14T19:13:45.155Z","dependency_job_id":"c60ce35d-d087-4284-9854-4ee0c3837857","html_url":"https://github.com/andrewzah/dotacr","commit_stats":null,"previous_names":["azah/dotacr"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewzah%2Fdotacr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewzah%2Fdotacr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewzah%2Fdotacr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andrewzah%2Fdotacr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andrewzah","download_url":"https://codeload.github.com/andrewzah/dotacr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252108858,"owners_count":21696150,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crystal","dota","steam-api","wrapper"],"created_at":"2024-08-02T17:01:07.475Z","updated_at":"2025-05-02T21:31:47.527Z","avatar_url":"https://github.com/andrewzah.png","language":"Crystal","funding_links":[],"categories":["Third-party APIs"],"sub_categories":[],"readme":"![Logo](https://i.imgur.com/DekYueq.png)\n\n[![Build Status](https://travis-ci.org/azah/dotacr.svg?branch=master)](https://travis-ci.org/azah/dotacr)   [![docs](https://img.shields.io/badge/docs-latest-green.svg)](https://azah.github.io/dotacr/doc/)\n\n# dotacr\n\nA Crystal client for the [DotA 2 API](https://wiki.teamfortress.com/wiki/WebAPI#Dota_2).\n\n## Installation\n\nAdd this to your application's `shard.yml`:\n\n```yaml\ndependencies:\n  dota:\n    github: azah/dotacr\n```\n\n## Usage\n\n\n```crystal\nrequire \"dota\"\n```\n\nGet your steam API key [here](https://steamcommunity.com/login/home/?goto=%2Fdev%2Fapikey), and configure Dotacr to use it:\n\n```crystal\nDota.configure do |config|\n  config.api_key = \"abcxyz\"\n\n  # Set API version (defaults to \"v1\")\n  # config.api_version = \"v1\"\nend\n```\n\nThen use the client:\n\n```crystal\napi = Dota.api\n```\n\n## Supported API Methods\n```crystal\napi.hero(13)                            # =\u003e (Cached) A single hero - \"Puck\"\napi.heroes                              # =\u003e (Cached) All heroes\n\napi.item(114)                           # =\u003e (Cached) A single item - \"Heart of Tarrasque\"\napi.items                               # =\u003e (Cached) All items\n\napi.ability(5003)                       # =\u003e (Cached) A single ability - \"Mana Break\"\napi.abilities                           # =\u003e (Cached) All abilities\n\napi.team(1375614)                       # =\u003e A single team - \"Newbee\"\napi.teams                               # =\u003e A list of teams\n\napi.teams({\"after\" =\u003e 1375614})         # Allowed options:\n                                        #\n                                        # :after - Integer, With team IDs equal or greater than this\n                                        # :limit - Integer, Amount of teams to return (default is 100)\n\napi.leagues                             # =\u003e All leagues\n\napi.matches(789645621)                  # =\u003e A single match - \"Newbee vs Vici Gaming\"\napi.matches                             # =\u003e A list of matches\napi.matches({\"hero_id\" =\u003e 43})          # Allowed options:\n                                        #\n                                        # :hero_id     - Integer, With this hero. See Dota::API::Hero.mapping\n                                        # :after       - Integer, With match IDs equal or greater than this\n                                        # :player_id   - Integer, With this player (32-bit Steam ID)\n                                        # :league_id   - Integer, In this league. Use Dota.leagues to get a list of leagues\n                                        # :mode_id     - Integer, In this game mode. See Dota::API::Match::MODES\n                                        # :skill_level - Integer, In this skill level (ignored if :player_id is provided). See Dota::API::Match::SkillLevels\n                                        # :from        - Integer, Minimum timestamp\n                                        # :to          - Integer, Maximum timestamp\n                                        # :min_players - Integer, With at least this number of players\n                                        # :league_only - Boolean, Only league matches\n                                        # :limit       - Integer, Amount of matches to return (default is 100)\n\napi.live_matches                        # =\u003e All live league matches\napi.live_matches({\"league_id\" =\u003e 600})  # Allowed options:\n                                        #\n                                        # :league_id - Integer, In this league. Use Dota.leagues to get a list of leagues\n                                        # :match_id  - Integer, With this match\n\napi.cosmetic_rarities                   # =\u003e All cosmetic rarities\n\napi.friends(76561198052976237)           # =\u003e All friends of user\n```\n\n## Custom Requests\n\nFor the unsupported endpoints, you can use `api.get`. For example, the following code is similar to `api.matches(789645621)` except it will return the raw JSON payload instead of an array of `Dota::Match`es.\n\n```crystal\napi.get(\u003cMethod\u003e, \u003cClass\u003e, \u003cInterface\u003e, \u003cOptions Hash\u003e)\napi.get(\"GetMatchDetails\", API::Match, \"IDOTA2Match_570\", {\"match_id\" =\u003e 789645621})\n```\n\n**Note**: For queries that return an array of objects, you must use the relative list class:\n* Match =\u003e MatchesList\n* BasicMatch =\u003e BasicMatchesList\n* League =\u003e LeaguesList\n* etc.\n\nYou can also get the response as `JSON::Any`, with `#get_JSON_any`:\n\n```crystal\napi.get_JSON_any(\"GetMatchDetails\", \"IDOTA2Match_570\", {\"match_id\" =\u003e 789645621, \"api_version\" =\u003e \"v1\"})\n```\n\n## API Objects\n\n### Hero\n\n```crystal\nhero.id        # Int8, ID of the hero\nhero.name      # String, Name of the hero\nhero.image_url # String, URL of the hero portrait\n```\n\n### Item\n\n```crystal\nitem.id        # Int32\nitem.name      # String\nitem.image_url # String\n```\n\n### Ability\n\n```crystal\nability.id        # Int32\nability.name      # String -\u003e \"Beserker's Call\"\nability.fullName  # String -\u003e \"Axe Beserker's Call\"\n```\n\n### Team\nTeamsList:\n\n```crystal\nlist.status  # Int8\nlist.teams   # Array(Dota::API::Team)\n```\n\n```crystal\nteam.player_ids                   # Array(Int32)\nteam.name                         # String\nteam.tag                          # String\nteam.country_code                 # String, ISO 3166-1 country code (see http://en.wikipedia.org/wiki/ISO_3166-1#Current_codes)\nteam.admin_id                     # Integer, Team admin's 32-bit Steam ID\nteam.player_ids                   # Array[Integer], Players' 32-bit Steam IDs\nteam.logo                         # String, UGC ID of the team's logo\nteam.logo_sponsor                 # String, UGC ID of the team's logo\nteam.url                          # String, URL of the team's website\nteam.time_created                 # Int32\nteam.games_played                 # Int16\nteam.player0_id                   # Int32 | Nil\n...\nteam.player6_id                   # Int32 | Nil\nteam.calibration_games_remaining  # Int8\n```\n\n#### League\n`LeaguesList` has one member: `leagues: Array(Dota::API::League)`.\n\n```crystal\nleague.id          # Int32\nleague.name        # String\nleague.description # String\nleague.url         # String\nleague.itemdef     # Int32\n\nDota::API::League::Tiers\nenum Tiers\n    Amateur      = 1\n    Professional\n    Premier\nend\n```\n\n#### Match\n\nCaveat: Getting a list of matches via `api.matches` will call [GetMatchHistory](https://wiki.teamfortress.com/wiki/WebAPI/GetMatchHistory) which has very few attributes for the matches returned (obviously for performance reasons), as opposed to getting info about a particular match via `api.matches(id)` which will instead call [GetMatchDetails](https://wiki.teamfortress.com/wiki/WebAPI/GetMatchDetails). The former uses `Dota::API::BasicMatch`, the latter uses `Dota::API::Match`.\n\n#### Dota::API::BasicMatch\nThe response will always be `Dota::API::BasicMatchesList`, even if there are 0 results.\n\n```crystal\nlist.status             # Int32\nlist.num_results        # Int32\nlist.total_results      # Int32\nlist.results_remaining  # Int32\nlist.matches            # Array(Dota::API::BasicMatch)\n```\n\n```crystal\nbasicMatch.match_id        # Int64\nbasicmatch.match_seq_num   # Int64\nbasicMatch.start_time      # Int32\nbasicMatch.lobby_type      # Dota::API::MatchStatus::GameModes\nbasicMatch.radiant_team_id # In32\nbasicMatch.dire_team_id    # Int32\nbasicMatch.players         # Array(Dota::API::BasicPlayer)\n```\n\nBasicPlayer:\n```crystal\naccount_id    # Int64 | Nil\nplayer_slot   # Int8\nhero_id       # Int32\n```\n\n#### Dota::API::Match\n`Dota::API::MatchesList` has one member: `matches: Array(Dota::API::Match)`.\n\n```crystal\nmatch.radiant                 # Dota::API::Match::Side\nmatch.dire                    # Dota::API::Match::Side\nmatch.id                      # Int64\nmatch.radiant_win             # Bool\nmatch.duration                # Int32, Length of the match, in seconds since the match began\nmatch.pre_game_duration       # Int32\nmatch.start_time              # Int32\nmatch.match_seq_num           # Int64\nmatch.tower_status_radiant    # Enum, Dota::API::MatchStatus::Towers\nmatch.tower_status_dire       # Enum, Dota::API::MatchStatus::Towers\nmatch.barracks_status_radiant # Enum, Dota::API::MatchStatus::Barracks\nmatch.barracks_status_dire    # Enum, Dota::API::MatchStatus::Barracks\nmatch.cluster                 # Int32\nmatch.first_blood_time        # Int32\nmatch.lobby_type              # Enum, Dota::API::MatchStatus::GameModes\nmatch.human_players           # Int8\nmatch.leagueid                # Int32\nmatch.positive_votes          # Int32\nmatch.negative_votes          # Int32\nmatch.game_mode               # Enum, Dota::API::MatchStatus::GameModes\nmatch.flags                   # Int32\nmatch.engine                  # Int32\nmatch.radiant_score           # Int32,\nmatch.dire_score              # Int32,\nmatch.radiant_team_id         # Int32 | Nil\nmatch.radiant_name            # String | Nil\nmatch.radiant_logo            # String | Nil\nmatch.radiant_team_complete   # Int32 | Nil\nmatch.dire_team_id            # Int32 | Nil\nmatch.dire_name               # String | Nil\nmatch.dire_team_complete      # Int32 | Nil\nmatch.radiant_captain         # Int32 | Nil\nmatch.dire_captain            # Int32 | Nil\nmatch.picks_bans              # Array(Dota::API::Match::Draft) | Nil, Picks and bans in the match, if the game mode is \"Captains Mode\"\nmatch.players                 # Array(Dota::API::Match::Player) | Nil\n\n# Dota::API::Match::Draft\ndraft.order          # Integer, 1-20\ndraft.pick?          # Boolean, true if the draft is a pick, and not a ban\ndraft.team           # Enum, Dota::API::PlayerStatus::Teams\ndraft.hero_id        # Int32\n\n# Dota::API::Match::Player\nplayer.account_id    # Int64\nplayer.player_slot   # Int8\nplayer.hero_id       # Int8\nplayer.kills         # Int16\nplayer.deaths        # Int16\nplayer.assists       # Int16\nplayer.leaver_status # Dota::API::PlayerStatus::Status\nplayer.last_hits     # Int16\nplayer.denies        # Int16\nplayer.gold_per_min  # Int16\nplayer.xp_per_min    # Int16\nplayer.item0_id      # Int16\nplayer.item1_id      # Int16\nplayer.item2_id      # Int16\nplayer.item3_id      # Int16\nplayer.item4_id      # Int16\nplayer.item5_id      # Int16\n\n# Dota::API::Match::Side\nside.score           # Int32\nside.barracks_status # Dota::API::MatchStatus::Barracks\nside.tower_status    # Dota::API::MatchStatus::Towers\nside.team_id         # Int32 | Nil\nside.team_name       # String | Nil\nside.team_logo       # String | Nil\nside.team_complete   # Int32 | Nil\nside.picks_bans      # Array(Dota::API::Match::Draft) | Nil\nside.players         # Array(Dota::API::Match::Player) | Nil\n```\n\n#### Live Matches\n`Dota::API::LiveMatchesList` has one member: `liveMatches: Array(Dota::API::Match)`.\n\n```crystal\nlive_match.radiant          # Dota::API::LiveMatch::Side\nlive_match.dire             # Dota::API::LiveMatch::Side\n\nlive_match.id               # Int64\nlive_match.lobby_id         # Int64\nlive_match.spectators       # Int32\nlive_match.league_id        # Int32\nlive_match.stream_delay     # Int32, Number of seconds the stream is behind actual game time\nlive_match.series_type      # Int8, Best of X series\nlive_match.league_tier      # Enum, Dota::API::League::Tiers\nlive_match.duration         # Integer, Length of the match, in seconds since the match began\nlive_match.roshan_timer     # Int16\nlive_match.scoreboard       # Dota::API::LiveMatch::Scoreboard\nlive_match.players          # Array(Dota::API::LiveMatch::SimplePlayer)\nlive_match.dire_team        # Dota::API::LiveMatch::Team\n\nSimplePlayer\nsp.account_id               # Int64\nsp.name                     # String\nsp.hero_id                  # Int32\nsp.team                     # Enum, Dota::API::PlayerStatus::Teams\n\nTeam\nt.name                      # String\nt.id                        # Int64\nt.logo                      # String\nt.complete                  # Bool\n\nScoreboard\nsb.duration                 # Float32\nsb.roshan_respawn_timer     # Int16\nsb.radiant                  # Dota::API::LiveMatch::Side\nsb.dire                     # Dota::API::LiveMatch::Side\n```\n\n### Side\n```crystal\nside.score           # Int32\nside.tower_state     # Enum, Dota::API::MatchStatus::Towers\nside.barracks_state  # Enum, Dota::API::MatchStatus::Barracks\nside.picks           # Array(Pick) | Nil\nside.bans            # Array(Bans) | Nil\nside.players         # Array(LivePlayer)\nside.abilities       # Array(Ability) | Nil\n\nPick\npick.hero_id         # Int32\n\nBan\nban.hero_id          # Int32\n\nAbility\nablity_id            # Int32\nability_level        # Int8\n\nLivePlayer\nlp.account_id         # Int64\nlp.player_slot        # Int8\nlp.level              # Int8\nlp.kills              # Int16\nlp.deaths             # Int16\nlp.assists            # Int16\nlp.denies             # Int16\nlp.gold               # Int32\nlp.gold_per_min       # Int16\nlp.xp_per_min         # Int16\nlp.ultimate_state     # Int8\nlp.ultimate_cooldown  # Int32\nlp.respawn_timer      # Int32\nlp.position_x         # Float32\nlp.position_y         # Float32\nlp.net_worth          # Int32\nlp.item0_id           # Int16\n...\nlp.item5_id           # Int16\n```\n\n### Friends\n`Dota::API::FriendsList` has one member: `friends: Array(Dota::API::Friend)`.\n\n```crystal\nfriend.steamid         # String\nfriend.relationship    # String\nfriend.friend_since    # Int32\n```\n\n## Resources\n\n- [vinnicc/dota](https://github.com/vinnicc/dota) The ruby version of this wrapper, and the inspiration behind it.\n- [Steam-Powered DOTA on Rails](http://www.sitepoint.com/steam-powered-dota-on-rails/) and [DOTA 2 on Rails: Digging Deeper](http://www.sitepoint.com/dota-2-rails-digging-deeper/) by Ilya Bodrov-Krukowski - A tutorial for getting personal match statistics that makes use of this library for Steam integration. (www.sitepoint.com)\n- [Things You Should Know Before Starting API Development](http://dev.dota2.com/showthread.php?t=58317) by MuppetMaster42 (dev.dota2.com)\n- [Dota 2 WebAPI Wiki](https://wiki.teamfortress.com/wiki/WebAPI#Dota_2) (wiki.teamfortress.com)\n- [Dota 2 WebAPI Forums](http://dev.dota2.com/forumdisplay.php?f=411) (dev.dota2.com)\n\n## Contributing\n\n1. Fork it ( https://github.com/azah/dotacr/fork )\n2. Create your feature branch (git checkout -b my-new-feature)\n3. Commit your changes (git commit -am 'Add some feature')\n4. Push to the branch (git push origin my-new-feature)\n5. Create a new Pull Request\n\n## Contributors\n\n- [azah](https://github.com/azah) Andrew Zah - creator, maintainer\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewzah%2Fdotacr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandrewzah%2Fdotacr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandrewzah%2Fdotacr/lists"}