NobGit
public imalexnord read

Discord-Hetzner-Bot

No description yet

Languages

Repository composition by tracked source files.

Python
Python 100%
Create file Wiki Documentation
Clone
https://nobgit.com/user/imalexnord/discord-hetzner-bot.git
ssh://[email protected]:2222/user/imalexnord/discord-hetzner-bot.git
game.py
from hcloud import Client
from hcloud.images.domain import Image
from hcloud.servers.domain import Server
from hcloud.server_types.domain import ServerType
from hcloud.volumes.domain import Volume
from hcloud.locations.domain import Location
import asyncio

class GameData:
    running = False

    def __init__(self, token, name, servertype, snapshot, location, volume):
        self.name = name
        self.servertype = servertype.strip() if isinstance(servertype, str) else servertype
        self.client = Client(token=token)

        # --- snapshot/image (optional) ---
        # If snapshot is None => we'll fall back to Ubuntu 24.04 in start()
        self.snapshot = None
        if snapshot is not None:
            images = self.client.images.get_all()
            for img in images:
                # support matching by description OR name
                if img.data_model.description == snapshot or img.data_model.name == snapshot:
                    self.snapshot = img.data_model.id
                    break
            if self.snapshot is None:
                raise ValueError(f"Snapshot/Image not found: {snapshot}")

        # --- location (required) ---
        self.location = None
        locations = self.client.locations.get_all()
        for loc in locations:
            if loc.data_model.name == location:
                self.location = loc.data_model.id
                break
        if self.location is None:
            raise ValueError(f"Location not found: {location}")

        # --- volume (optional) ---
        self.volume = None
        if volume is not None:
            volumes = self.client.volumes.get_all()
            for vol in volumes:
                if vol.data_model.name == volume and vol.data_model.location.data_model.id == self.location:
                    self.volume = vol.data_model.id
                    break
            if self.volume is None:
                raise ValueError(f"Volume not found in location {location}: {volume}")

        # --- check for existing server by name ---
        servers = self.client.servers.get_all()
        self.server = None
        for s in servers:
            if s.data_model.name == name:
                self.server = s  # keep the Server object
                self.running = True
                print("existing server " + self.server.status)

    async def start(self):
        if not self.running:
            print("Starting " + self.name)

            # Choose image:
            # - if snapshot provided => use that snapshot image id
            # - else => boot from Ubuntu 24.04 (Hetzner public image name)
            image = Image(self.snapshot) if self.snapshot is not None else "ubuntu-24.04"

            # Attach volume only if configured
            volumes = [Volume(self.volume)] if self.volume is not None else None

            response = self.client.servers.create(
                name=self.name,
                server_type=ServerType(name=self.servertype),
                image=image,
                location=Location(self.location),
                volumes=volumes
            )
            self.server = response.server
            self.running = True
        else:
            print(self.name + " is already running")

    async def stop(self):
        if self.running:
            print("Stopping " + self.name)

            self.client.servers.shutdown(self.server)

            # Give it time to begin shutdown, then poll status
            await asyncio.sleep(5)

            while True:
                serv = self.client.servers.get_by_id(self.server.id)
                self.server = serv
                print(self.server.status)
                if self.server.status == Server.STATUS_OFF:
                    break
                await asyncio.sleep(5)

            print("Server is now stopped")

            # Detach volume only if configured
            if self.volume is not None:
                self.client.volumes.detach(Volume(self.volume))
                await asyncio.sleep(1)

            self.client.servers.delete(self.server)
            self.running = False
            self.server = None
        else:
            print(self.name + " isn't running")

    def status(self):
        msg = self.name
        if self.server is None:
            msg += " isn't running"
        else:
            self.server = self.client.servers.get_by_id(self.server.id)
            msg += " is in status "
            msg += self.server.status
            msg += "\n"
            msg += "and has the IP:\n"
            ip = self.server.public_net.ipv4.ip
            msg += ip + "\n"
        return msg

    def isRunning(self):
        return self.running