import os import json class MetaDataManager: _instance = None def __new__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super().__new__(cls) cls._instance.init() return cls._instance def init(self): self.socket = None # read metadata file from executing directory self.metadata_file = os.path.join(os.getcwd(), "metadata.json") if os.path.exists(self.metadata_file): with open(self.metadata_file, "r") as f: self.collections = json.load(f) else: self.collections = {} if(collections := next((c for c in self.collections if c.get("name") == "Uncategorized"), None)) is None: self.collections.append({"name": "Uncategorized", "id": 0, "clips": []}) self.save_metadata() def create_collection(self, name): if any(c.get("name") == name for c in self.collections): raise ValueError(f"Collection '{name}' already exists.") new_id = max((c.get("id", 0) for c in self.collections), default=0) + 1 self.collections.append({"name": name, "id": new_id, "clips": []}) self.save_metadata() def delete_collection(self, name): collection = next((c for c in self.collections if c.get("name") == name), None) if collection is None: raise ValueError(f"Collection '{name}' does not exist.") self.collections.remove(collection) self.save_metadata() def add_clip_to_collection(self, collection_name, clip_metadata): collection = next((c for c in self.collections if c.get("name") == collection_name), None) if collection is None: raise ValueError(f"Collection '{collection_name}' does not exist.") collection["clips"].append(clip_metadata) if not self.socket is None: self.socket.emit('collection_updated', collection) self.save_metadata() def remove_clip_from_collection(self, collection_name, clip_metadata): collection = next((c for c in self.collections if c.get("name") == collection_name), None) if collection is None: raise ValueError(f"Collection '{collection_name}' does not exist.") # Remove all clips with the same file name as clip_metadata["file_name"] in_list = any(clip.get("filename") == clip_metadata.get("filename") for clip in collection["clips"]) if not in_list: raise ValueError(f"Clip with filename '{clip_metadata.get('filename')}' not found in collection '{collection_name}'.") collection["clips"] = [ clip for clip in collection["clips"] if clip.get("filename") != clip_metadata.get("filename") ] if not self.socket is None: self.socket.emit('collection_updated', collection) self.save_metadata() def move_clip_to_collection(self, source_collection, target_collection, clip_metadata): self.remove_clip_from_collection(source_collection, clip_metadata) self.add_clip_to_collection(target_collection, clip_metadata) if not self.socket is None: self.socket.emit('collection_updated', source_collection) self.socket.emit('collection_updated', target_collection) def edit_clip_in_collection(self, collection_name, new_clip_metadata): collection = next((c for c in self.collections if c.get("name") == collection_name), None) if collection is None: raise ValueError(f"Collection '{collection_name}' does not exist.") # Find the index of the clip with the same file name as old_clip_metadata["file_name"] index = next((i for i, clip in enumerate(collection["clips"]) if clip.get("filename") == new_clip_metadata.get("filename")), None) if index is None: raise ValueError(f"Clip with filename '{new_clip_metadata.get('filename')}' not found in collection '{collection_name}'.") collection["clips"][index] = new_clip_metadata if not self.socket is None: self.socket.emit('collection_updated', collection) self.save_metadata() def get_collections(self): return list(map(lambda c: {"name": c.get("name"), "id": c.get("id")}, self.collections)) def get_clips_in_collection(self, collection_name): collection = next((c for c in self.collections if c.get("name") == collection_name), None) if collection is None: raise ValueError(f"Collection '{collection_name}' does not exist.") return collection["clips"] def reorder_clips_in_collection(self, collection_name, new_order): collection = next((c for c in self.collections if c.get("name") == collection_name), None) if collection is None: raise ValueError(f"Collection '{collection_name}' does not exist.") existing_filenames = {clip.get("filename") for clip in collection["clips"]} new_filenames = {clip.get("filename") for clip in new_order} if not new_filenames.issubset(existing_filenames): raise ValueError("New order contains clips that do not exist in the collection.") collection["clips"] = new_order if not self.socket is None: self.socket.emit('collection_updated', collection) self.save_metadata() def save_metadata(self): with open(self.metadata_file, "w") as f: json.dump(self.collections, f, indent=4)