-
-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #129 from Hornochs/add_automate_server_to_discord
Adding Python Script to automatically add Servers to DiscordGSM
- Loading branch information
Showing
3 changed files
with
287 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
# DiscordGSM Server Automation Script | ||
|
||
Command-line tool to automate adding game servers to DiscordGSM's SQLite database. | ||
|
||
## Requirements | ||
|
||
- Python 3.6+ | ||
- SQLite3 | ||
- Access to DiscordGSM's `servers.db` file | ||
- **Important**: Must run in DiscordGSM's virtual environment | ||
```bash | ||
source /path/to/discordgsm/venv/bin/activate # Linux/Mac | ||
# or | ||
\path\to\discordgsm\venv\Scripts\activate # Windows | ||
``` | ||
|
||
## Installation | ||
|
||
1. Save `add_server.py` to your desired location | ||
2. Ensure you have write access to DiscordGSM's database directory | ||
|
||
## Usage | ||
|
||
### Command Line | ||
|
||
```bash | ||
python3 add_server.py \ | ||
--guild_id YOUR_GUILD_ID \ | ||
--channel_id YOUR_CHANNEL_ID \ | ||
--game_id GAME_ID \ | ||
--address SERVER_ADDRESS \ | ||
--query_port QUERY_PORT \ | ||
[--db_path PATH_TO_DB] \ | ||
[--ignore-existing] | ||
``` | ||
|
||
### Arguments | ||
|
||
Required: | ||
- `--guild_id`: Discord server (guild) ID | ||
- `--channel_id`: Discord channel ID | ||
- `--game_id`: Game identifier (e.g., "minecraft", "valheim") | ||
- `--address`: Server address/hostname | ||
- `--query_port`: Query port number | ||
|
||
Optional: | ||
- `--db_path`: Custom path to `servers.db` (defaults to `./data/servers.db`) | ||
- `--ignore-existing`: Continue execution if server already exists | ||
|
||
## Examples | ||
|
||
Basic usage: | ||
```bash | ||
python3 add_server.py \ | ||
--guild_id 123456789 \ | ||
--channel_id 987654321 \ | ||
--game_id minecraft \ | ||
--address mc.example.com \ | ||
--query_port 25565 | ||
``` | ||
|
||
Ignoring existing servers: | ||
```bash | ||
python3 add_server.py \ | ||
--guild_id 123456789 \ | ||
--channel_id 987654321 \ | ||
--game_id valheim \ | ||
--address valheim.example.com \ | ||
--query_port 2457 \ | ||
--ignore-existing | ||
``` | ||
|
||
## Error Handling | ||
|
||
- Validates database existence | ||
- Checks for existing servers with same address and query port | ||
- Provides detailed error messages including channel and game info for existing servers | ||
- Returns exit code 1 on error unless `--ignore-existing` is set | ||
|
||
## Ansible Integration | ||
|
||
Use `add_servers.yml` for automated deployment: | ||
|
||
```yaml | ||
vars: | ||
ignore_existing: true # Set to false to fail on existing servers | ||
``` | ||
Key features: | ||
- Database existence validation | ||
- Optional failure on existing servers (`ignore_existing`) | ||
- Detailed output summary | ||
- Proper idempotency handling |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import sqlite3 | ||
import json | ||
from typing import Optional, Dict, Tuple | ||
from dataclasses import dataclass | ||
import os | ||
from pathlib import Path | ||
import argparse | ||
import sys | ||
|
||
@dataclass | ||
class ServerConfig: | ||
guild_id: int | ||
channel_id: int | ||
game_id: str | ||
address: str | ||
query_port: int | ||
query_extra: Dict = None | ||
style_id: str = "Medium" | ||
style_data: Dict = None | ||
position: Optional[int] = None | ||
status: bool = False | ||
result: Dict = None | ||
message_id: Optional[int] = None | ||
|
||
class DGSMAutomation: | ||
def __init__(self, db_path: str = None): | ||
if db_path is None: | ||
db_path = os.path.join(Path(__file__).parent, "data", "servers.db") | ||
self.db_path = db_path | ||
if not os.path.exists(self.db_path): | ||
raise FileNotFoundError(f"Database not found at {self.db_path}") | ||
self._init_db() | ||
|
||
def _init_db(self): | ||
with sqlite3.connect(self.db_path) as conn: | ||
cursor = conn.cursor() | ||
cursor.execute(''' | ||
CREATE TABLE IF NOT EXISTS servers ( | ||
id INTEGER PRIMARY KEY AUTOINCREMENT, | ||
position INT NOT NULL, | ||
guild_id BIGINT NOT NULL, | ||
channel_id BIGINT NOT NULL, | ||
message_id BIGINT, | ||
game_id TEXT NOT NULL, | ||
address TEXT NOT NULL, | ||
query_port INT(5) NOT NULL, | ||
query_extra TEXT NOT NULL, | ||
status INT(1) NOT NULL, | ||
result TEXT NOT NULL, | ||
style_id TEXT NOT NULL, | ||
style_data TEXT NOT NULL | ||
) | ||
''') | ||
conn.commit() | ||
|
||
def server_exists(self, address: str, query_port: int) -> Tuple[bool, Optional[Dict]]: | ||
with sqlite3.connect(self.db_path) as conn: | ||
cursor = conn.cursor() | ||
cursor.execute( | ||
'SELECT channel_id, game_id FROM servers WHERE address = ? AND query_port = ?', | ||
(address, query_port) | ||
) | ||
result = cursor.fetchone() | ||
if result: | ||
return True, { | ||
'channel_id': result[0], | ||
'game_id': result[1] | ||
} | ||
return False, None | ||
|
||
def add_server(self, config: ServerConfig) -> Tuple[bool, str]: | ||
try: | ||
exists, existing_data = self.server_exists(config.address, config.query_port) | ||
if exists: | ||
return False, f"Server {config.address}:{config.query_port} already exists in channel {existing_data['channel_id']} for game {existing_data['game_id']}" | ||
|
||
with sqlite3.connect(self.db_path) as conn: | ||
cursor = conn.cursor() | ||
|
||
if config.position is None: | ||
cursor.execute( | ||
'SELECT COALESCE(MAX(position + 1), 0) FROM servers WHERE channel_id = ?', | ||
(config.channel_id,) | ||
) | ||
config.position = cursor.fetchone()[0] | ||
|
||
config.query_extra = config.query_extra or {} | ||
config.style_data = config.style_data or {"locale": "en-US", "timezone": "UTC"} | ||
config.result = config.result or {"name": "", "map": "", "password": False, "raw": {}, "connect": "", "numplayers": 0, "numbots": 0, "maxplayers": 0, "players": [], "bots": []} | ||
|
||
cursor.execute(''' | ||
INSERT INTO servers ( | ||
position, guild_id, channel_id, game_id, address, query_port, | ||
query_extra, status, result, style_id, style_data, message_id | ||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) | ||
''', ( | ||
config.position, | ||
config.guild_id, | ||
config.channel_id, | ||
config.game_id, | ||
config.address, | ||
config.query_port, | ||
json.dumps(config.query_extra), | ||
int(config.status), | ||
json.dumps(config.result), | ||
config.style_id, | ||
json.dumps(config.style_data), | ||
config.message_id | ||
)) | ||
conn.commit() | ||
return True, f"Successfully added server {config.address}:{config.query_port}" | ||
except sqlite3.Error as e: | ||
return False, f"Database error: {str(e)}" | ||
except Exception as e: | ||
return False, f"Unexpected error: {str(e)}" | ||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description='Add server to DiscordGSM') | ||
parser.add_argument('--guild_id', type=int, required=True) | ||
parser.add_argument('--channel_id', type=int, required=True) | ||
parser.add_argument('--game_id', type=str, required=True) | ||
parser.add_argument('--address', type=str, required=True) | ||
parser.add_argument('--query_port', type=int, required=True) | ||
parser.add_argument('--db_path', type=str, help='Path to servers.db') | ||
parser.add_argument('--ignore-existing', action='store_true', help='Continue if server exists') | ||
|
||
args = parser.parse_args() | ||
|
||
try: | ||
automation = DGSMAutomation(db_path=args.db_path) | ||
|
||
server_config = ServerConfig( | ||
guild_id=args.guild_id, | ||
channel_id=args.channel_id, | ||
game_id=args.game_id, | ||
address=args.address, | ||
query_port=args.query_port | ||
) | ||
|
||
success, message = automation.add_server(server_config) | ||
print(message) | ||
|
||
if not success and not args.ignore_existing: | ||
sys.exit(1) | ||
|
||
except Exception as e: | ||
print(f"Error: {str(e)}") | ||
sys.exit(1) | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
--- | ||
- name: Add servers to DiscordGSM | ||
hosts: localhost | ||
gather_facts: no | ||
|
||
vars: | ||
discordgsm_db: "/path/to/servers.db" | ||
ignore_existing: true # Set to false to fail on existing servers | ||
servers: | ||
- guild_id: 123456789 | ||
channel_id: 987654321 | ||
game_id: "minecraft" | ||
address: "mc.example.com" | ||
query_port: 25565 | ||
# Add more servers as needed | ||
|
||
tasks: | ||
- name: Ensure DiscordGSM database exists | ||
stat: | ||
path: "{{ discordgsm_db }}" | ||
register: db_check | ||
failed_when: not db_check.stat.exists | ||
|
||
- name: Add server to DiscordGSM | ||
command: > | ||
python3 add_server.py | ||
--guild_id {{ item.guild_id }} | ||
--channel_id {{ item.channel_id }} | ||
--game_id {{ item.game_id }} | ||
--address {{ item.address }} | ||
--query_port {{ item.query_port }} | ||
--db_path {{ discordgsm_db }} | ||
{% if ignore_existing %}--ignore-existing{% endif %} | ||
register: result | ||
failed_when: | ||
- result.rc != 0 | ||
- not ignore_existing | ||
changed_when: "'Successfully added server' in result.stdout" | ||
with_items: "{{ servers }}" | ||
|
||
- name: Show results | ||
debug: | ||
msg: "{{ result.results | map(attribute='stdout_lines') | list }}" |