├── csgo-gsi-python ├── payloadparser.py ├── gamestate.py ├── server.py └── information.py ├── README.md ├── LICENSE ├── gamestate_integration_GSI.cfg └── .gitignore /csgo-gsi-python/payloadparser.py: -------------------------------------------------------------------------------- 1 | import gamestate 2 | 3 | class PayloadParser: 4 | def parse_payload(self, payload, gamestate): 5 | for item in payload: 6 | for i in payload[item]: 7 | try: 8 | setattr(getattr(gamestate, item), i, payload[item][i]) 9 | except: 10 | pass 11 | -------------------------------------------------------------------------------- /csgo-gsi-python/gamestate.py: -------------------------------------------------------------------------------- 1 | import information 2 | 3 | class GameState: 4 | def __init__(self): 5 | self.player = information.Player() 6 | self.map = information.Map() 7 | self.provider = information.Provider() 8 | self.phase_countdowns = information.PhaseCountdowns() 9 | self.bomb = information.Bomb() 10 | self.round = information.Round() 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # csgo-gsi-python 2 | 3 | python library to interact with CS:GO Game State Integration. 4 | 5 | ## Simple usage 6 | Copy the **gamestate_integration_GSI.cfg** file to *C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Global Offensive\csgo\cfg* 7 | ```py 8 | server = GSIServer(("127.0.0.1", 3000), "S8RL9Z6Y22TYQK45JB4V8PHRJJMD9DS9") 9 | server.start_server() 10 | 11 | server.get_info("map", "name") 12 | server.get_info("player", "state", "flashed) 13 | ``` 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Erlend 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /gamestate_integration_GSI.cfg: -------------------------------------------------------------------------------- 1 | "GSI v1.0.0" 2 | { 3 | "uri" "http://127.0.0.1:3000" 4 | "timeout" "5.0" 5 | "buffer" "0.1" 6 | "throttle" "0.1" 7 | "heartbeat" "30.0" 8 | "auth" 9 | { 10 | "token" "S8RL9Z6Y22TYQK45JB4V8PHRJJMD9DS9" 11 | } 12 | "data" 13 | { 14 | "provider" "1" 15 | "phase_countdowns" "1" 16 | "map_round_wins" "1" 17 | "round" "1" 18 | "bomb" "1" 19 | "map" "1" 20 | "player_match_stats" "1" 21 | "player_position" "1" 22 | "player_weapons" "1" 23 | "player_state" "1" 24 | "player_id" "1" 25 | 26 | "allgrenades" "0" 27 | "allplayers_id" "0" 28 | "allplayers_match_stats" "0" 29 | "allplayers_position" "0" 30 | "allplayers_state" "0" 31 | "allplayers_weapons" "0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /csgo-gsi-python/server.py: -------------------------------------------------------------------------------- 1 | from http.server import BaseHTTPRequestHandler, HTTPServer 2 | from operator import attrgetter 3 | from threading import Thread 4 | import json 5 | 6 | import gamestate 7 | import payloadparser 8 | 9 | class GSIServer(HTTPServer): 10 | def __init__(self, server_address, auth_token): 11 | super(GSIServer, self).__init__(server_address, RequestHandler) 12 | 13 | self.auth_token = auth_token 14 | self.gamestate = gamestate.GameState() 15 | self.parser = payloadparser.PayloadParser() 16 | 17 | self.running = False 18 | 19 | def start_server(self): 20 | try: 21 | thread = Thread(target=self.serve_forever) 22 | thread.start() 23 | first_time = True 24 | while self.running == False: 25 | if first_time == True: 26 | print("CS:GO GSI Server starting..") 27 | first_time = False 28 | except: 29 | print("Could not start server.") 30 | 31 | def get_info(self, target, *argv): 32 | try: 33 | if len(argv) == 0: 34 | state = attrgetter(f"{target}")(self.gamestate) 35 | elif len(argv) == 1: 36 | state = attrgetter(f"{target}.{argv[0]}")(self.gamestate) 37 | elif len(argv) == 2: 38 | state = attrgetter(f"{target}.{argv[0]}")(self.gamestate)[f"{argv[1]}"] 39 | else: 40 | print("Too many arguments.") 41 | return False 42 | if "object" in str(state): 43 | return vars(state) 44 | else: 45 | return state 46 | except Exception as E: 47 | print(E) 48 | return False 49 | 50 | class RequestHandler(BaseHTTPRequestHandler): 51 | def do_POST(self): 52 | length = int(self.headers["Content-Length"]) 53 | body = self.rfile.read(length).decode("utf-8") 54 | 55 | payload = json.loads(body) 56 | 57 | if not self.authenticate_payload(payload): 58 | print("auth_token does not match.") 59 | return False 60 | else: 61 | self.server.running = True 62 | 63 | self.server.parser.parse_payload(payload, self.server.gamestate) 64 | 65 | def authenticate_payload(self, payload): 66 | if "auth" in payload and "token" in payload["auth"]: 67 | return payload["auth"]["token"] == self.server.auth_token 68 | else: 69 | return False 70 | -------------------------------------------------------------------------------- /csgo-gsi-python/information.py: -------------------------------------------------------------------------------- 1 | """ 2 | Classes to represent Player information 3 | """ 4 | class Player: 5 | """Class to store player information""" 6 | def __init__(self): 7 | self.name = None 8 | self.activity = None 9 | self.forward = None 10 | self.position = None 11 | self.observer_slot = None 12 | self.team = None 13 | self.clan = None 14 | self.steamid = None 15 | self.spectarget = None 16 | self.state = State() 17 | self.match_stats = MatchStats() 18 | self.weapons = {} 19 | 20 | class State: 21 | """Class to store player state information""" 22 | def __init__(self): 23 | self.armor = None 24 | self.burning = None 25 | self.equip_value = None 26 | self.flashed = None 27 | self.health = None 28 | self.helmet = None 29 | self.money = None 30 | self.round_killhs = None 31 | self.round_kills = None 32 | self.round_totaldmg = None 33 | self.smoked = None 34 | 35 | class MatchStats: 36 | """Class to store player match stats information""" 37 | def __init__(self): 38 | self.assists = None 39 | self.deaths = None 40 | self.kills = None 41 | self.mvps = None 42 | self.score = None 43 | 44 | 45 | """ 46 | Classes to represent Map information 47 | """ 48 | class Map: 49 | """Class to store map information""" 50 | def __init__(self): 51 | self.round_wins = None 52 | self.current_spectators = None 53 | self.mode = None 54 | self.name = None 55 | self.num_matches_to_win_series = None 56 | self.phase = None 57 | self.round = None 58 | self.souvenirs_total = None 59 | self.team_ct = Team() 60 | self.team_t = Team() 61 | 62 | class Team: 63 | """Class to store map teams information""" 64 | def __init__(self): 65 | self.consecutive_round_losses = None 66 | self.matches_won_this_series = None 67 | self.score = None 68 | self.name = None 69 | self.timeouts_remaining = None 70 | 71 | 72 | """ 73 | Class to represent Provider information 74 | """ 75 | class Provider: 76 | """Class to store provider information""" 77 | def __init__(self): 78 | self.appid = None 79 | self.name = None 80 | self.steamid = None 81 | self.timestamp = None 82 | self.version = None 83 | self.update_info = None 84 | 85 | 86 | """ 87 | Class to represent Phase Countdowns information 88 | """ 89 | class PhaseCountdowns: 90 | """Class to store phase countdowns information""" 91 | def __init__(self): 92 | self.phase = None 93 | self.phase_ends_in = None 94 | 95 | 96 | """ 97 | Class to represent Bomb information 98 | """ 99 | class Bomb: 100 | """Class to store bomb information""" 101 | def __init__(self): 102 | self.player = None 103 | self.position = None 104 | self.state = None 105 | self.countdown = None 106 | 107 | 108 | """ 109 | Class to represent Round information 110 | """ 111 | class Round: 112 | """Class to store round information""" 113 | def __init__(self): 114 | self.phase = None 115 | self.win_team = None 116 | self.bomb = None 117 | --------------------------------------------------------------------------------