from datetime import datetime import firebase_admin import jwt from firebase_admin import auth, credentials, firestore from google.api_core.exceptions import Aborted, DataLoss, NotFound, OutOfRange, PermissionDenied, ResourceExhausted import file_manager cred = credentials.Certificate('secrets/servii.json') app = firebase_admin.initialize_app(cred) firestore_database = firestore.client() ''' TODO Write a function that launches upon app's startup, it does check in the firestore for any already running servers. Fetches the PID's. Stops all the current processes, Tell the database they have now stopped running. Also ensure the program can add an additional argument to avoid this checking for scalability. ''' def get_user_from_id(user_id): return auth.get_user(user_id) def verify_jwt_token(token): try: decoded_token = jwt.decode(token, options={"verify_signature": False}) user_id = decoded_token.get('sub') return True, user_id except jwt.ExpiredSignatureError: return False, None except jwt.InvalidTokenError: return False, None def fetch_port() -> int or None: servers_ref = firestore_database.collection("users") query = servers_ref.order_by("port", direction="DESCENDING").limit(1) highest_port_doc = next(query.stream(), None) if highest_port_doc: return highest_port_doc.get('port') return None def user_field_exists(user_id: str, field: str) -> bool: try: doc = firestore_database.collection('users').document(user_id).get() if doc.exists: return True return False except NotFound: return False def server_name_taken(user_id: str, server_name: str) -> bool: servers = firestore_database.collection('users').document(user_id).collection('servers') query = servers.where(field_path='name', op_string='==', value=server_name) for _ in query.stream(): return True return False def get_user_field(user_id, field_name): user_doc_ref = firestore_database.collection('users').document(user_id) user_doc = user_doc_ref.get() if user_doc.exists: field_value = user_doc.to_dict().get(field_name) return field_value else: return None def get_server_port(user_id: str) -> int or None: try: servers_ref = firestore_database.collection('users').document(user_id) server_doc = servers_ref.get() port = server_doc.get('port') return port if port else None except Exception: return None def create_firestore(user_id: str, data: dict) -> bool: doc_ref = firestore_database.collection('users').document(user_id) try: doc_ref.create(data) return True except (NotFound, PermissionDenied, Aborted, ResourceExhausted, OutOfRange, DataLoss, TypeError, Exception, ValueError) as e: log_exception_to_firestore(e, user_id, data) return False def update_firestore(user_id: str, data: dict) -> bool: doc_ref = firestore_database.collection('users').document(user_id) try: doc_ref.update(data) return True except (NotFound, PermissionDenied, Aborted, ResourceExhausted, OutOfRange, DataLoss, TypeError, Exception, ValueError) as e: log_exception_to_firestore(e, user_id, data) return False def set_firestore(user_id: str, data: dict) -> bool: doc_ref = firestore_database.collection('users').document(user_id) try: doc_ref.set(data) return True except (NotFound, PermissionDenied, Aborted, ResourceExhausted, OutOfRange, DataLoss, TypeError, Exception, ValueError) as e: log_exception_to_firestore(e, user_id, data) return False def create_server(user_id: str, server_name: str, version: str, port: str, framework: str = "paper"): port: int = int(port) servers_ref = firestore_database.collection('users').document(user_id).collection('servers') server_doc_ref = servers_ref.document(server_name) server_doc_ref.set( {'name': server_name, 'port': port, 'running': False, 'version': version, 'framework': framework, "difficulty": "easy", "gamemode": "survival", "forceGamemode": "false", "hardcore": "false", "generateStructures": "true", "motd": "A Minecraft Server", "pvp": "true", "onlineMode": "true", "maxPlayers": 20, "enableCommandBlock": "false"}) def delete_server(user_id: str, server_name: str): user_ref = firestore_database.collection('users').document(user_id) servers_ref = user_ref.collection('servers') server_doc_ref = servers_ref.document(server_name) server_doc_ref.delete() def delete_user(user_id: str): user_ref = firestore_database.collection('users').document(user_id) user_ref.delete() def update_server_running_state(user_id: str, server_name: str, state: bool): server_ref = firestore_database.collection('users').document(user_id).collection('servers').document(server_name) if server_ref.get().get('running') != state: server_ref.update({'running': state}) def update_server_property(user_id: str, server_name: str, prop: str, value: str): server_ref = firestore_database.collection('users').document(user_id).collection('servers').document(server_name) prop = file_manager.kebab_to_camel_case(prop) server_ref.update({prop: value}) def log_exception_to_firestore(exception: Exception = None, user_id: str = None, data: dict = None): new_id: str = datetime.now().strftime('%Y-%m-%d %H:%M:%S %Z%z') log_entry = { 'exception_name': str(type(exception).__name__), 'exception': str(exception) if exception else 'No exception', 'user_id': str(user_id) if user_id else 'No user_id', 'data': str(data) if data else 'No data provided', } try: firestore_database.collection('firebase.logs').document(new_id).create(log_entry) print("Log entry added successfully.") except Exception as e: print(f"Failed to add log entry: {e}") if __name__ == "__main__": pass