119 lines
5.9 KiB
Python
119 lines
5.9 KiB
Python
from . import rcon
|
|
import asyncio
|
|
from typing import Union
|
|
import logging
|
|
|
|
arcon_log = logging.getLogger('arcon_lib')
|
|
|
|
|
|
class ARKServer(rcon.RCONConnection):
|
|
def __init__(self, *args, monitor_chat: bool = False, server_chat_channel: int = None,
|
|
server_messages_channel: int = None, **kwargs):
|
|
self.monitor_chat = monitor_chat
|
|
self.server_chat_channel = server_chat_channel
|
|
self.server_messages_channel = server_messages_channel
|
|
super().__init__(*args, **kwargs)
|
|
|
|
async def run_command(self, command: str, multi_packet: bool = False, reconnect_counter: int = 0) \
|
|
-> Union[rcon.RCONPacket, str]:
|
|
arcon_log.debug(f'Command requested: {command}')
|
|
if self.authenticated:
|
|
packet = rcon.RCONPacket(next(self.packet_id), rcon.SERVERDATA_EXECCOMMAND, command)
|
|
with await self.lock:
|
|
try:
|
|
arcon_log.debug(f'Sending packet {packet.packet_id}')
|
|
await self.send_packet(packet)
|
|
arcon_log.debug(f'Packet Sent.')
|
|
except ConnectionResetError:
|
|
arcon_log.info(f'Connection to {self.host}:{self.port} lost, Reconnecting...')
|
|
self.lock.release()
|
|
await self._reconnect_and_resend(packet)
|
|
await self.lock.acquire()
|
|
finally:
|
|
arcon_log.debug(f'Waiting for response to packet {packet.packet_id}')
|
|
try:
|
|
response = await self.read(packet, multi_packet=multi_packet)
|
|
except asyncio.TimeoutError as e:
|
|
if reconnect_counter > 5:
|
|
return 'Reached max reconnects. Closing connection.'
|
|
arcon_log.warning(f'No response received: {e}\nAttempting to reconnect #{reconnect_counter}')
|
|
self.lock.release()
|
|
await self._reconnect()
|
|
await self.lock.acquire()
|
|
response = await self.run_command(command=command, multi_packet=multi_packet,
|
|
reconnect_counter=reconnect_counter + 1)
|
|
arcon_log.debug(f'Response Received:\n{response.packet_type}:{response.packet_id}:{response.body}')
|
|
response.body = response.body.strip('\x00\x00').strip()
|
|
return response
|
|
else:
|
|
return 'Server is not Authenticated. Please let the Admin know of this issue.'
|
|
|
|
async def getchat(self) -> str:
|
|
response = await self.run_command(command='getchat', multi_packet=True)
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def saveworld(self) -> str:
|
|
response = await self.run_command(command='saveworld')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def serverchat(self, message: str) -> str:
|
|
response = await self.run_command(command=f'serverchat {message}')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def broadcast(self, message: str) -> str:
|
|
response = await self.run_command(command=f'broadcast {message}')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def listplayers(self) -> str:
|
|
response = await self.run_command(command=f'listplayers')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def whitelist(self, steam_id: str) -> str:
|
|
response = await self.run_command(command=f'AllowPlayerToJoinNoCheck {steam_id}')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def ban_player(self, steam_id: int) -> str:
|
|
response = await self.run_command(command=f'BanPlayer {steam_id}')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def unban_player(self, steam_id: int) -> str:
|
|
response = await self.run_command(command=f'UnbanPlayer {steam_id}')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def kick_player(self, steam_id: int) -> str:
|
|
response = await self.run_command(command=f'KickPlayer {steam_id}')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def stop_server(self) -> int:
|
|
saved = await self.saveworld()
|
|
if saved == 'World Saved':
|
|
await self.serverchat(saved)
|
|
await asyncio.sleep(10)
|
|
response = await self.run_command(command='DoExit')
|
|
if response.body == 'Exiting...':
|
|
return 0
|
|
else:
|
|
return 2
|
|
else:
|
|
return 1
|
|
|
|
async def get_logs(self):
|
|
response = await self.run_command(command=f'GetGameLog', multi_packet=True)
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def server_chat_to_steam_id(self, steam_id: int, message: str) -> str:
|
|
response = await self.run_command(command=f'ServerChatTo {steam_id} {message}')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def server_chat_to_player_name(self, player_name: str, message: str) -> str:
|
|
response = await self.run_command(command=f'ServerChatToPlayer "{player_name}" {message}')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def set_time_of_day(self, hour: int, minute: int = 00, seconds: int = 00) -> str:
|
|
response = await self.run_command(command=f'SetTimeOfDay {hour}:{minute}:{seconds}')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|
|
|
|
async def destroy_wild_dinos(self):
|
|
response = await self.run_command(command='DestroyWildDinos')
|
|
return response.body if isinstance(response, rcon.RCONPacket) else response
|