From 1e8e8c324fa3d715cfff7e0a6af1126ad19c1c28 Mon Sep 17 00:00:00 2001 From: CD Date: Fri, 6 Mar 2026 21:22:39 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EC=9C=A0=EB=A0=B9=20=EC=9B=8C=ED=81=AC?= =?UTF-8?q?=EC=8A=A4=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EB=8C=80=EC=8B=A0=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=B4=EC=A1=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - cleanup_orphans: 삭제 -> _orphan_YYYYMMDD 접미사 추가 - Git/Vikunja 설정 등 모든 데이터 보존됨 - 이름 충돌 없이 같은 이름으로 새 채널 등록 가능 --- api/discord_bot.py | 2 +- core/workspace.py | 43 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/api/discord_bot.py b/api/discord_bot.py index 15ba38c..66ef30c 100644 --- a/api/discord_bot.py +++ b/api/discord_bot.py @@ -128,7 +128,7 @@ async def on_ready(): orphans = ws_manager.cleanup_orphans(all_channel_ids) if orphans: names = ", ".join(ws.name for ws in orphans) - logger.info(f"유령 워크스페이스 {len(orphans)}개 정리: {names}") + logger.info(f"유령 워크스페이스 {len(orphans)}개 보존(이름 변경): {names}") # 등록된 워크스페이스 표시 ws_list = ws_manager.list_all() diff --git a/core/workspace.py b/core/workspace.py index 8353294..d16fada 100644 --- a/core/workspace.py +++ b/core/workspace.py @@ -160,21 +160,48 @@ class WorkspaceManager: ] def cleanup_orphans(self, valid_channel_ids: set[int]) -> list[Workspace]: - """존재하지 않는 채널의 워크스페이스 정리. + """존재하지 않는 채널의 워크스페이스를 이름 변경하여 보존. - Returns: 제거된 워크스페이스 목록 (알림용) + 삭제하지 않고 이름에 _orphan_날짜 접미사를 붙여 보존합니다. + 기존 설정(Git, Vikunja)은 그대로 유지됩니다. + + Returns: 이름 변경된 워크스페이스 목록 (알림용) """ - orphans = [] + from datetime import datetime + + renamed = [] + suffix = f"_orphan_{datetime.now().strftime('%Y%m%d')}" + for ch_id, ws in list(self.workspaces.items()): if ch_id not in valid_channel_ids: - orphans.append(ws) - del self.workspaces[ch_id] - logger.info(f"유령 워크스페이스 제거: {ws.name} (채널 {ch_id} 없음)") + old_name = ws.name + # 이미 orphan 접미사가 있으면 스킵 + if "_orphan_" in ws.name: + continue + ws.name = f"{ws.name}{suffix}" + ws.channel_id = 0 # 채널 바인딩 해제 + renamed.append(ws) + logger.info( + f"유령 워크스페이스 보존: {old_name} -> {ws.name} " + f"(채널 {ch_id} 없음, 설정 유지)" + ) - if orphans: + if renamed: + # 유령 항목은 channel_id=0 으로 이동 + to_remove = [ + ch_id for ch_id in self.workspaces + if ch_id not in valid_channel_ids and "_orphan_" not in self.workspaces[ch_id].name + ] + # 이미 이름 변경됐으므로 키만 정리 + for ch_id in list(self.workspaces.keys()): + if self.workspaces[ch_id].channel_id == 0 and ch_id != 0: + ws = self.workspaces.pop(ch_id) + # orphan은 이름을 키로 저장 (음수 해시) + orphan_key = -abs(hash(ws.name)) % (10**10) + self.workspaces[orphan_key] = ws self._save() - return orphans + return renamed def set_git(self, channel_id: int, url: str, token: str, repo: str = "", branch: str = "main") -> bool: