Skip to content

Commit

Permalink
Support mongodb
Browse files Browse the repository at this point in the history
  • Loading branch information
BattlefieldDuck committed Oct 31, 2023
1 parent a43739d commit c2ef735
Show file tree
Hide file tree
Showing 8 changed files with 471 additions and 143 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,6 @@ dmypy.json

# discordgsm
data/logs/*txt
data/exports/
data/servers.db
data/servers.sql
node_modules
public/static/guilds.json
sponsors.json
510 changes: 405 additions & 105 deletions discordgsm/database.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion discordgsm/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def __int__(self) -> int:
Variable('APP_ADVERTISE_TYPE', 'Presence advertise type. server_count = 0, individually = 1, player_stats = 2', AdvertiseType, default=0),
Variable('TASK_QUERY_SERVER', 'Query servers task scheduled time in seconds.', float, default=60),
Variable('TASK_QUERY_SERVER_TIMEOUT', 'Query servers task timeout in seconds.', float, default=15),
Variable('DB_CONNECTION', 'Database type. Accepted value: sqlite, pgsql', str, default='sqlite'),
Variable('DB_CONNECTION', 'Database type. Accepted value: sqlite, pgsql, mongodb', str, default='sqlite'),
Variable('DATABASE_URL', 'Database connection url.', str),
Variable('COMMAND_QUERY_PUBLIC', 'Whether the /queryserver command should be available to all users.', bool, default=False),
Variable('COMMAND_QUERY_COOLDOWN', 'The /queryserver command cooldown in seconds. (Administrator will not be affected)', float, default=5),
Expand Down
4 changes: 4 additions & 0 deletions discordgsm/gamedig.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ def is_port_valid(port: str):
return 0 <= port_number <= 65535

async def query(self, server: Server):
# Backward compatibility
if server.game_id == 'forrest':
server.game_id = 'forest'

return await self.run({**{
'type': server.game_id,
'host': server.address,
Expand Down
4 changes: 2 additions & 2 deletions discordgsm/games.csv
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ crysis2,Crysis 2 (2011),gamespy3,port=64000
crysiswars,Crysis Wars (2008),gamespy3,port=64100
cs15,Counter-Strike 1.5 (2002),won,port=27015
cs16,Counter-Strike 1.6 (2003),source,port=27015
cs2,Counter-Strike 2 (2023),source,port=27015
cscz,Counter-Strike: Condition Zero (2004),source,port=27015
csgo,Counter-Strike: Global Offensive (2012),source,port=27015
css,Counter-Strike: Source (2004),source,port=27015
cs2,Counter-Strike 2 (2023),source,port=27015

daikatana,Daikatana (2000),quake2,port=27982;port_query_offset=10
darkesthour,Darkest Hour: Europe '44-'45 (2008),unreal2,port=7757;port_query_offset=1
Expand Down Expand Up @@ -127,12 +127,12 @@ halo,Halo (2003),gamespy2,port=2302
halo2,Halo 2 (2007),gamespy2,port=2302
heretic2,Heretic II (1998),gamespy1,port=27900;port_query_offset=1
hexen2,Hexen II (1997),hexen2,port=26900;port_query_offset=50
hfnaw,Holdfast: Nations at War (2020),source,port=27000
hidden,The Hidden (2005),source,port=27015
hl2dm,Half-Life 2: Deathmatch (2004),source,port=27015
hldm,Half-Life Deathmatch (1998),source,port=27015
hldms,Half-Life Deathmatch: Source (2005),source,port=27015
hll,Hell Let Loose (2021),source,port=27015
hfnaw,Holdfast: Nations at War (2020),source,port=27000
homefront,Homefront (2011),source,port=27015
homeworld2,Homeworld 2 (2003),gamespy1,port_query=6500
hurtworld,Hurtworld (2015),source,port=12871;port_query=12881
Expand Down
21 changes: 9 additions & 12 deletions discordgsm/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def cache_message(message: Message):
intents = discord.Intents.default()
shard_ids = [int(shard_id) for shard_id in os.getenv('APP_SHARD_IDS').replace(';', ',').split(',') if shard_id] if len(os.getenv('APP_SHARD_IDS', '')) > 0 else None
shard_count = int(os.getenv('APP_SHARD_COUNT', '1'))
client = Client(intents=intents) if not public else AutoShardedClient(intents=intents, shard_ids=shard_ids, shard_count=shard_count)
client = AutoShardedClient(intents=intents, shard_ids=shard_ids, shard_count=shard_count)


# region Application event
Expand All @@ -53,7 +53,7 @@ async def on_ready():
"""Called when the client is done preparing the data received from Discord."""
await client.wait_until_ready()

Logger.info(f'Connected to {database.type} database')
Logger.info(f'Connected to {database.driver.value} database')
Logger.info(f'Logged on as {client.user}')
Logger.info(f'Add to Server: {invite_link}')

Expand Down Expand Up @@ -92,7 +92,7 @@ async def on_guild_join(guild: discord.Guild):
@client.event
async def on_guild_remove(guild: discord.Guild):
"""Remove all associated servers in database when discordgsm leaves"""
database.factory_reset(guild.id)
database.delete_servers(guild_id=guild.id)
Logger.info(f'{client.user} left {guild.name}({guild.id}), associated servers were deleted.')


Expand Down Expand Up @@ -266,7 +266,7 @@ async def modal_on_submit(interaction: Interaction):
for item in params.values():
item.default = item._value = str(item._value).strip()

game_id, address, query_port = game['id'], str(query_param['host']), str(query_param['port'])
game_id, address, query_port = game['id'], str(query_param['host']), int(str(query_param['port']))

# Validate the port number
for key in params.keys():
Expand Down Expand Up @@ -396,7 +396,7 @@ async def command_delserver(interaction: Interaction, address: str, query_port:

if server := await find_server(interaction, address, query_port):
await interaction.response.defer(ephemeral=True)
database.delete_server(server)
database.delete_servers(servers=[server])

if await resend_channel_messages(interaction):
await interaction.delete_original_response()
Expand Down Expand Up @@ -428,7 +428,7 @@ async def command_factoryreset(interaction: Interaction):
async def button_callback(interaction: Interaction):
await interaction.response.defer(ephemeral=True)
servers = database.all_servers(guild_id=interaction.guild.id)
database.factory_reset(interaction.guild.id)
database.delete_servers(guild_id=interaction.guild.id)

async def purge_channel(channel_id: int):
channel = client.get_channel(channel_id)
Expand Down Expand Up @@ -544,7 +544,7 @@ async def command_editstyledata(interaction: Interaction, address: str, query_po
async def modal_on_submit(interaction: Interaction):
await interaction.response.defer(ephemeral=True)
server.style_data.update({k: str(v) for k, v in edit_fields.items()})
database.update_server_style_data(server)
database.update_servers_style_data([server])
await refresh_channel_messages(interaction)

modal.on_submit = modal_on_submit
Expand All @@ -567,11 +567,8 @@ async def command_switch(interaction: Interaction, channel: discord.TextChannel,

if servers := await find_servers(interaction, address, query_port):
await interaction.response.defer(ephemeral=True)
database.update_servers(servers, channel_id=channel.id)

for server in servers:
server.channel_id = channel.id

database.update_servers_channel_id(servers)
await resend_channel_messages(None, interaction.channel.id)
await resend_channel_messages(None, channel.id)

Expand Down Expand Up @@ -683,7 +680,7 @@ async def modal_on_submit(interaction: Interaction):
webhook_url = str(text_input_webhook_url).strip()
content = str(text_input_webhook_content).strip()
server.style_data.update({'_alert_webhook_url': webhook_url, '_alert_content': content})
database.update_server_style_data(server)
database.update_servers_style_data([server])

modal.on_submit = modal_on_submit
await interaction.response.send_modal(modal)
Expand Down
68 changes: 48 additions & 20 deletions discordgsm/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,27 @@
from discordgsm.gamedig import GamedigResult


@dataclass
class QueryServer:
game_id: str
address: str
query_port: int
query_extra: dict
status: bool
result: GamedigResult

@staticmethod
def create(row: tuple) -> QueryServer:
return QueryServer(
game_id=row[0],
address=row[1],
query_port=row[2],
query_extra=json.loads(row[3]),
status=row[4] == 1,
result=json.loads(row[5]),
)


@dataclass
class Server:
id: int
Expand All @@ -17,15 +38,15 @@ class Server:
message_id: Optional[int]
game_id: str
address: str
query_port: str
query_port: int
query_extra: dict
status: bool
result: GamedigResult
style_id: str
style_data: dict

@staticmethod
def new(guild_id: int, channel_id: int, game_id: str, address: str, query_port: str, query_extra: dict, result: GamedigResult) -> Server:
def new(guild_id: int, channel_id: int, game_id: str, address: str, query_port: int, query_extra: dict, result: GamedigResult) -> Server:
return Server(
id=None,
position=None,
Expand All @@ -42,24 +63,6 @@ def new(guild_id: int, channel_id: int, game_id: str, address: str, query_port:
style_data={}
)

@staticmethod
def from_distinct_query(row: tuple) -> Server:
return Server(
id=None,
position=None,
guild_id=None,
channel_id=None,
message_id=None,
game_id=row[0],
address=row[1],
query_port=row[2],
query_extra=json.loads(row[3]),
status=row[4] == 1,
result=json.loads(row[5]),
style_id=None,
style_data=None,
)

@staticmethod
def from_list(row: tuple, filter_secret=False) -> Server:
query_extra: dict = json.loads(row[8])
Expand All @@ -85,3 +88,28 @@ def from_list(row: tuple, filter_secret=False) -> Server:
style_id=row[11],
style_data=style_data,
)

@staticmethod
def from_docs(data: dict, filter_secret=False) -> Server:
server = Server(
id=data['_id'],
position=data['position'],
guild_id=data['guild_id'],
channel_id=data['channel_id'],
message_id=data.get('message_id'),
game_id=data['game_id'],
address=data['address'],
query_port=data['query_port'],
query_extra=data['query_extra'],
status=data['status'],
result=data['result'],
style_id=data['style_id'],
style_data=data['style_data']
)

if filter_secret:
# Filter key started with _ and filter the description since it may contain secrets
server.query_extra = {k: v for k, v in server.query_extra.items() if not str(k).startswith('_')}
server.style_data = {k: v for k, v in server.style_data.items() if not str(k).startswith('_') and k != 'description'}

return server
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Flask==3.0.0
gunicorn==21.2.0
opengsq==2.1.2
psycopg2-binary==2.9.9
pymongo==4.5.0
python-dotenv==1.0.0
pywin32==306;platform_system=="Windows"
tzdata==2023.3

0 comments on commit c2ef735

Please sign in to comment.