Merge remote-tracking branch 'origin/master'

This commit is contained in:
cclecle
2023-06-28 21:23:20 +01:00
6 changed files with 171 additions and 30 deletions

View File

@@ -19,6 +19,7 @@ from . import RconQuakes
from . import RconUTEngineWebAdminUT2k4
from . import RconUTEngineWebAdminUT3
from . import RconUTEngineWebAdminUT99
from . import RconUT99_ChaChaRESTStats
from . import RconMinecraft
from pickle import TRUE
from concurrent.futures import ThreadPoolExecutor
@@ -123,7 +124,7 @@ class GameStatsSupervisorFactory:
self._RconFactory = RconBase.RconFactory()
self.register_GameStatsSupervisorRconBuilder("ut2k4", RconUTEngineWebAdminUT2k4.RconUTEngineWebAdminUT2k4)
self.register_GameStatsSupervisorRconBuilder("ut3", RconUTEngineWebAdminUT3.RconUTEngineWebAdminUT3)
self.register_GameStatsSupervisorRconBuilder("ut99", RconUTEngineWebAdminUT99.RconUTEngineWebAdminUT99)
self.register_GameStatsSupervisorRconBuilder("ut99", RconUTEngineWebAdminUT99.RconUT99_ChaChaRESTStats)
self.register_GameStatsSupervisorRconBuilder("q2", RconQuakes.RconSourceEngineQuake2)
self.register_GameStatsSupervisorRconBuilder("q3a", RconQuakes.RconSourceEngineQuake3A)
self.register_GameStatsSupervisorRconBuilder("codmw3", RconCODs.RconSourceEngineCODMW3)

View File

@@ -0,0 +1,93 @@
"""
ChaChaGameStats (c) by clement chastanier
ChaChaGameStats is licensed under a
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
You should have received a copy of the license along with this
work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
"""
import time
from pprint import pprint
import requests
from . import GameStatsInterface
from . import RconBase
#class ExceptionRconIncorrectPadding(RconBase.ExceptionRcon):
# pass
class RconUT99_ChaChaRESTStats(RconBase.RconBase):
def __init__(self,GameName:str,ip:str,port:int,user:str,password:str,timeout:int):
print("INIT ???")
super().__init__(GameName,ip,port,user,password,timeout)
self.session = None
self.BaseUrl = "http://" + self.ip + ":" + str(self.port) + "/api/v1/"
self.GameServerStatusResult = None
self.timeout = timeout
def connect(self):
self.session = requests.session()
super().connect()
def disconnect(self):
try:
self.session.close()
except Exception as e:
print("WARNING: self.session.close() failed: %s" % e)
super().disconnect()
def GetStatus(self) -> dict():
PINGstarttime = time.time()
defaults_all=self.session.get(self.BaseUrl + "defaults_all",timeout=self.timeout)
PING = round( (time.time() - PINGstarttime)*1000)
current_all=self.session.get(self.BaseUrl + "current_all",timeout=self.timeout)
res=dict()
res["ping"]=PING
res["defaults_all"]=defaults_all.json()
res["current_all"]=current_all.json()
return res
## interface implementation
def GetGameServerStatusResult(self) -> GameStatsInterface.GameServerStatusResult_Main:
self.GameServerStatusResult = super().GetGameServerStatusResult()
if self.GameServerStatusResult.status != "DOWN":
try:
self.GameServerStatusResult.raw = self.GetStatus()
self.GameServerStatusResult.status = "UP"
except RconBase.ExceptionRconTimeout:
self.GameServerStatusResult.status = "DOWN"
self.GameServerStatusResult.ping = 999
return self.GameServerStatusResult
except RconBase.ExceptionWrongRconPassword:
self.GameServerStatusResult.status = "REFUSED"
self.GameServerStatusResult.ping = 999
return self.GameServerStatusResult
self.GameServerStatusResult.name = self.GameServerStatusResult.raw["defaults_all"]["ServerName"]
self.GameServerStatusResult.map = self.GameServerStatusResult.raw["current_all"]["Level"]
self.GameServerStatusResult.gametype = self.GameServerStatusResult.raw["current_all"]["GameName"]
self.GameServerStatusResult.mods = ", ".join(self.GameServerStatusResult.raw["current_all"]["Mutators"])
self.GameServerStatusResult.maxplayers = self.GameServerStatusResult.raw["defaults_all"]["MaxPlayers"]
self.GameServerStatusResult.ping = self.GameServerStatusResult.raw["ping"]
self.GameServerStatusResult.version = None
self.GameServerStatusResult.players = []
numplayers = 0
for player in self.GameServerStatusResult.raw["current_all"]["player_list"]:
if player["bIsSpectator"] or player["bIsABot"]:
continue
newplayer = GameStatsInterface.GameServerStatusResult_Players()
newplayer.name = player["PlayerName"]
newplayer.score = player["Score"]
newplayer.ping = player["Ping"]
newplayer.ip = player["IP"]
newplayer.port = None
newplayer.uid = None
newplayer.num = numplayers
self.GameServerStatusResult.players.append(newplayer)
numplayers+=1
self.GameServerStatusResult.nplayer = numplayers
return self.GameServerStatusResult

View File

@@ -46,7 +46,6 @@ class RconUTEngineWebAdmin(RconBase.RconBase,metaclass=abc.ABCMeta):
self.GameServerStatusResult = None
self.timeout = timeout
self.initConstant()
self.fetchData = {};
def initConstant(self):
pass
@@ -65,8 +64,7 @@ class RconUTEngineWebAdmin(RconBase.RconBase,metaclass=abc.ABCMeta):
def _fetchPageRAW(self,page) -> str:
try:
response = self.session.get(page,data=self.fetchData,timeout=self.timeout)
self.fetchData = {}
response = self.session.get(page,timeout=self.timeout)
if response.status_code != 200:
raise RconBase.ExceptionWrongRconPassword
except requests.exceptions.RequestException as e:
@@ -150,32 +148,47 @@ class RconUTEngineWebAdminMODCENTRAL(RconUTEngineWebAdmin,metaclass=abc.ABCMeta)
tree = self._fetchPageETree(url)
try:
level1 = tree.findall(".//form[@action='"+element+"']")[0]
level2 = level1.findall(".//table")[0]
infoChart = level2.findall(".//tr")
for info_record in infoChart:
data = info_record.findall(".//td/select")
if data :
attributename = data[0].attrib["name"].split('.')[-1] #get last var name: BLABLA.keyname => keyname
data_value = data[0].findall(".//option[@selected]")
level2 = level1.findall(".//table")
# table based page
if level2:
level2 = level2[0]
infoChart = level2.findall(".//tr")
for info_record in infoChart:
data = info_record.findall(".//td/select")
if data :
attributename = data[0].attrib["name"].split('.')[-1] #get last var name: BLABLA.keyname => keyname
data_value = data[0].findall(".//option[@selected]")
if data_value:
if "value" in data_value[0].attrib:
ar_ServerRules[attributename] = data_value[0].attrib["value"]
else:
ar_ServerRules[attributename] = data_value[0].text
continue
data = info_record.findall(".//td/input")
if data and data[0].attrib["name"]!="Apply":
attributename = data[0].attrib["name"].split('.')[-1] #get last var name: BLABLA.keyname => keyname
if "value" in data[0].attrib:
ar_ServerRules[attributename] = data[0].attrib["value"]
else:
ar_ServerRules[attributename] = data[0].text
if data[0].attrib["type"] == "checkbox" :
if "checked" in data[0].attrib:
ar_ServerRules[attributename] = "true"
else:
ar_ServerRules[attributename] = "false"
continue
else:
#new pages UT99 469c .... :-/
selects = level1.findall(".//select")
for _select in selects:
attributename = _select.attrib["name"].split('.')[-1] #get last var name: BLABLA.keyname => keyname
data_value = _select.findall(".//option[@selected]")
if data_value:
if "value" in data_value[0].attrib:
ar_ServerRules[attributename] = data_value[0].attrib["value"]
else:
ar_ServerRules[attributename] = data_value[0].text
continue
data = info_record.findall(".//td/input")
if data and data[0].attrib["name"]!="Apply":
attributename = data[0].attrib["name"].split('.')[-1] #get last var name: BLABLA.keyname => keyname
if "value" in data[0].attrib:
ar_ServerRules[attributename] = data[0].attrib["value"]
else:
ar_ServerRules[attributename] = data[0].text
if data[0].attrib["type"] == "checkbox" :
if "checked" in data[0].attrib:
ar_ServerRules[attributename] = "true"
else:
ar_ServerRules[attributename] = "false"
continue
continue
except Exception as e:
raise RconBase.ExceptionRconResultParse(e)
return ar_ServerRules

View File

@@ -171,8 +171,13 @@ class RconUTEngineWebAdminUT99(RconUTEngineWebAdmin.RconUTEngineWebAdminMODCENTR
ar_PlayersStats = []
tree = self._fetchPageETree(self.currentplayersUrl)
try:
level1 = tree.findall(".//form[@action='current_players']")[0]
level2 = level1.findall(".//table")[1]
level1 = tree.findall(".//form[@action='current_players']")
if len(level1) == 2: #ut469c
level1 = level1[1]
level2 = level1.findall(".//table")[0]
else:
level1 = level1[0]
level2 = level1.findall(".//table")[1]
player_chart = level2.findall(".//tr")
del player_chart[0]
for player_record in player_chart:

View File

@@ -7,4 +7,4 @@ Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported
You should have received a copy of the license along with this
work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
"""
__version__ = "0.1.4"
__version__ = "0.1.8"

View File

@@ -39,6 +39,33 @@ if __name__ == "__main__":
"""
ar_games.append( _GameStatsSupervisorFactory.create( name = "ut99-dm",
gametype = "ut99",
ip = "172.16.1.41",
Interface_QuakeStats = { "port":5000},
Interface_RconBase = { "port":5000,
"username":"chacha",
"password":"cfographut"}
)
)
"""
ar_games.append( _GameStatsSupervisorFactory.create( name = "ut99-ctf",
gametype = "ut99",
ip = "127.0.0.1",
#ip = "37.59.37.210",
#Interface_QuakeStats = { "port":5040},
Interface_RconBase = { "port":8080,
"username":"",
"password":""}
)
)
"""
ar_games.append( _GameStatsSupervisorFactory.create( name = "ut99-niut",
gametype = "ut99",
ip = "172.16.1.40",
@@ -62,7 +89,8 @@ if __name__ == "__main__":
"username":"chacha",
"password":"cfographut"}
)
)
)
ar_games.append( _GameStatsSupervisorFactory.create( name = "ut99-utp",
gametype = "ut99",
ip = "172.16.1.42",
@@ -76,6 +104,7 @@ if __name__ == "__main__":
)
)
ar_games.append( _GameStatsSupervisorFactory.create( name = "codbo2-3",
gametype = "codbo2",
ip = "GAME-CODBO2",
@@ -124,7 +153,7 @@ if __name__ == "__main__":
print("")
print("== Testing: " + game.GameName + "==")
res = game.API_GetGameServerStatusResult()
print("res: " + str(res.__dict__))
pprint("res: " + str(res.__dict__))
for player in res.players:
print(player.__dict__)
if "QuakeStats" in res.raw: