File size: 4,971 Bytes
e0249f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
"""
Backup / Restore serwera Minecraft do Hugging Face Dataset.

Usage:
    python3 sync_data.py restore
    python3 sync_data.py backup
"""

import os
import sys
import tarfile
import shutil
import tempfile
from pathlib import Path

from huggingface_hub import HfApi, hf_hub_download

# ── configuration ────────────────────────────────────────────────────────────

DATASET_ID = os.environ.get("DATASET_ID", "natekkz/basketrush-data")
HF_TOKEN = os.environ.get("HF_TOKEN", "")
SERVER_DIR = Path("/home/user/minecraft/server")
ARCHIVE_NAME = "server-backup.tar.gz"

# Directories to back up (relative to SERVER_DIR)
BACKUP_DIRS = [
    "world",
    "plugins",
    "config",
]

# Individual files to back up (relative to SERVER_DIR)
BACKUP_FILES = [
    "server.properties",
    "bukkit.yml",
    "spigot.yml",
    "commands.yml",
    "help.yml",
    "permissions.yml",
    "wepif.yml",
    "usercache.json",
    "whitelist.json",
    "banned-ips.json",
    "banned-players.json",
    "ops.json",
    "server-icon.png",
    "version_history.json",
]

# playit.gg configuration (persisted across restarts)
PLAYIT_TOML = Path.home() / ".config" / "playit" / "playit.toml"


# ── restore ──────────────────────────────────────────────────────────────────

def restore():
    """Download and extract server backup from HF Dataset."""
    if not HF_TOKEN:
        print("[sync] No HF_TOKEN set – skipping restore")
        return False

    print(f"[sync] Restoring from dataset {DATASET_ID}...")
    try:
        archive_path = hf_hub_download(
            repo_id=DATASET_ID,
            filename=ARCHIVE_NAME,
            repo_type="dataset",
            token=HF_TOKEN,
        )
    except Exception as e:
        print(f"[sync] No backup found in dataset ({e}) – starting fresh")
        return False

    SERVER_DIR.mkdir(parents=True, exist_ok=True)

    # Safe extraction β€” validate paths
    with tarfile.open(archive_path, "r:gz") as tar:
        for member in tar.getmembers():
            target = (SERVER_DIR / member.name).resolve()
            if not str(target).startswith(str(SERVER_DIR.resolve())):
                print(f"[sync] ⚠ Skipping unsafe path: {member.name}")
                continue
            tar.extract(member, path=SERVER_DIR)

    # Restore playit.gg config if present in backup
    playit_backup = SERVER_DIR / ".playit.toml"
    if playit_backup.exists():
        PLAYIT_TOML.parent.mkdir(parents=True, exist_ok=True)
        shutil.copy2(playit_backup, PLAYIT_TOML)
        print("[sync] Restored playit.toml")

    print("[sync] βœ… Restore complete")
    return True


# ── backup ───────────────────────────────────────────────────────────────────

def backup():
    """Create a tarball of server data and upload to HF Dataset."""
    if not HF_TOKEN:
        print("[sync] No HF_TOKEN set – skipping backup")
        return False

    print(f"[sync] Backing up to dataset {DATASET_ID}...")

    with tempfile.TemporaryDirectory() as tmp:
        archive_path = Path(tmp) / ARCHIVE_NAME

        with tarfile.open(archive_path, "w:gz") as tar:
            # Add directories
            for d in BACKUP_DIRS:
                src = SERVER_DIR / d
                if src.exists():
                    tar.add(str(src), arcname=d)
                    print(f"  + {d}/")

            # Add individual files
            for f in BACKUP_FILES:
                src = SERVER_DIR / f
                if src.exists():
                    tar.add(str(src), arcname=f)
                    print(f"  + {f}")

            # Include playit.gg config
            if PLAYIT_TOML.exists():
                tar.add(str(PLAYIT_TOML), arcname=".playit.toml")
                print("  + .playit.toml")

        # Upload
        api = HfApi(token=HF_TOKEN)
        api.upload_file(
            path_or_fileobj=str(archive_path),
            path_in_repo=ARCHIVE_NAME,
            repo_id=DATASET_ID,
            repo_type="dataset",
        )

    print("[sync] βœ… Backup uploaded")
    return True


# ── CLI ──────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python3 sync_data.py [restore|backup]")
        sys.exit(1)

    cmd = sys.argv[1].lower()
    if cmd == "restore":
        restore()
    elif cmd == "backup":
        backup()
    else:
        print(f"Unknown command: {cmd}")
        sys.exit(1)