sirochild commited on
Commit
159131f
·
verified ·
1 Parent(s): a73fa4e

Upload user_id_manager.py

Browse files
Files changed (1) hide show
  1. user_id_manager.py +241 -0
user_id_manager.py ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ユーザーID永続化管理モジュール
3
+ ローカル環境でユーザーIDをファイルに保存し、仮想環境を閉じても継続してプレイできるようにする
4
+ """
5
+ import os
6
+ import json
7
+ import uuid
8
+ import logging
9
+ from datetime import datetime
10
+ from typing import Optional, Dict, Any
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ class UserIDManager:
15
+ """ユーザーIDの永続化を管理するクラス"""
16
+
17
+ def __init__(self, storage_dir: str = "user_data"):
18
+ """
19
+ Args:
20
+ storage_dir: ユーザーデータを保存するディレクトリ
21
+ """
22
+ self.storage_dir = storage_dir
23
+ self.user_id_file = os.path.join(storage_dir, "user_id.json")
24
+ self._ensure_storage_dir()
25
+
26
+ def _ensure_storage_dir(self):
27
+ """ストレージディレクトリが存在することを確認"""
28
+ try:
29
+ if not os.path.exists(self.storage_dir):
30
+ os.makedirs(self.storage_dir)
31
+ logger.info(f"ユーザーデータディレクトリを作成: {self.storage_dir}")
32
+ except Exception as e:
33
+ logger.error(f"ストレージディレクトリ作成エラー: {e}")
34
+
35
+ def get_or_create_user_id(self) -> str:
36
+ """
37
+ 保存されたユーザーIDを取得するか、新規作成する
38
+
39
+ Returns:
40
+ ユーザーID
41
+ """
42
+ try:
43
+ # 既存のユーザーIDファイルをチェック
44
+ if os.path.exists(self.user_id_file):
45
+ user_data = self._load_user_data()
46
+ if user_data and "user_id" in user_data:
47
+ user_id = user_data["user_id"]
48
+ logger.info(f"既存のユーザーIDを読み込み: {user_id[:8]}...")
49
+
50
+ # 最終アクセス時刻を更新
51
+ self._update_last_access(user_id)
52
+ return user_id
53
+
54
+ # 新規ユーザーIDを作成
55
+ user_id = self._generate_new_user_id()
56
+ self._save_user_data(user_id)
57
+ logger.info(f"新規ユーザーIDを作成: {user_id[:8]}...")
58
+ return user_id
59
+
60
+ except Exception as e:
61
+ logger.error(f"ユーザーID取得エラー: {e}")
62
+ # フォールバック: 一時的なIDを生成
63
+ return str(uuid.uuid4())
64
+
65
+ def _generate_new_user_id(self) -> str:
66
+ """新しいユーザーIDを生成"""
67
+ return str(uuid.uuid4())
68
+
69
+ def _load_user_data(self) -> Optional[Dict[str, Any]]:
70
+ """ユーザーデータファイルを読み込み"""
71
+ try:
72
+ with open(self.user_id_file, 'r', encoding='utf-8') as f:
73
+ data = json.load(f)
74
+ return data
75
+ except Exception as e:
76
+ logger.error(f"ユーザーデータ読み込みエラー: {e}")
77
+ return None
78
+
79
+ def _save_user_data(self, user_id: str, game_data: Optional[Dict[str, Any]] = None):
80
+ """ユーザーデータをファイルに保存"""
81
+ try:
82
+ user_data = {
83
+ "user_id": user_id,
84
+ "created_at": datetime.now().isoformat(),
85
+ "last_access": datetime.now().isoformat(),
86
+ "version": "1.0",
87
+ "game_data": game_data or {}
88
+ }
89
+
90
+ with open(self.user_id_file, 'w', encoding='utf-8') as f:
91
+ json.dump(user_data, f, ensure_ascii=False, indent=2)
92
+
93
+ logger.info(f"ユーザーデータを保存: {self.user_id_file}")
94
+
95
+ except Exception as e:
96
+ logger.error(f"ユーザーデータ保存エラー: {e}")
97
+
98
+ def _update_last_access(self, user_id: str):
99
+ """最終アクセス時刻を更新"""
100
+ try:
101
+ user_data = self._load_user_data()
102
+ if user_data:
103
+ user_data["last_access"] = datetime.now().isoformat()
104
+
105
+ with open(self.user_id_file, 'w', encoding='utf-8') as f:
106
+ json.dump(user_data, f, ensure_ascii=False, indent=2)
107
+
108
+ logger.debug(f"最終アクセス時刻を更新: {user_id[:8]}...")
109
+
110
+ except Exception as e:
111
+ logger.error(f"最終アクセス時刻更新エラー: {e}")
112
+
113
+ def get_user_info(self) -> Optional[Dict[str, Any]]:
114
+ """ユーザー情報を取得"""
115
+ return self._load_user_data()
116
+
117
+ def delete_user_data(self) -> bool:
118
+ """
119
+ ユーザーデータを削除(フルリセット用)
120
+
121
+ Returns:
122
+ 削除成功かどうか
123
+ """
124
+ try:
125
+ if os.path.exists(self.user_id_file):
126
+ os.remove(self.user_id_file)
127
+ logger.info(f"ユーザーデータファイルを削除: {self.user_id_file}")
128
+ return True
129
+ else:
130
+ logger.info("削除対象のユーザーデータファイルが存在しません")
131
+ return True
132
+
133
+ except Exception as e:
134
+ logger.error(f"ユーザーデータ削除エラー: {e}")
135
+ return False
136
+
137
+ def reset_user_id(self) -> str:
138
+ """
139
+ ユーザーIDをリセットして新規作成
140
+
141
+ Returns:
142
+ 新しいユーザーID
143
+ """
144
+ try:
145
+ # 既存データを削除
146
+ self.delete_user_data()
147
+
148
+ # 新規IDを作成
149
+ new_user_id = self._generate_new_user_id()
150
+ self._save_user_data(new_user_id)
151
+
152
+ logger.info(f"ユーザーIDをリセット: {new_user_id[:8]}...")
153
+ return new_user_id
154
+
155
+ except Exception as e:
156
+ logger.error(f"ユーザーIDリセットエラー: {e}")
157
+ return str(uuid.uuid4())
158
+
159
+ def is_user_data_exists(self) -> bool:
160
+ """ユーザーデータファイルが存在するかチェック"""
161
+ return os.path.exists(self.user_id_file)
162
+
163
+ def get_storage_info(self) -> Dict[str, Any]:
164
+ """ストレージ情報を取得(デバッグ用)"""
165
+ try:
166
+ info = {
167
+ "storage_dir": self.storage_dir,
168
+ "user_id_file": self.user_id_file,
169
+ "file_exists": os.path.exists(self.user_id_file),
170
+ "dir_exists": os.path.exists(self.storage_dir)
171
+ }
172
+
173
+ if info["file_exists"]:
174
+ stat = os.stat(self.user_id_file)
175
+ info["file_size"] = stat.st_size
176
+ info["modified_time"] = datetime.fromtimestamp(stat.st_mtime).isoformat()
177
+
178
+ return info
179
+
180
+ except Exception as e:
181
+ logger.error(f"ストレージ情報取得エラー: {e}")
182
+ return {"error": str(e)}
183
+
184
+ def save_game_data(self, user_id: str, game_data: Dict[str, Any]) -> bool:
185
+ """
186
+ ゲームデータを保存
187
+
188
+ Args:
189
+ user_id: ユーザーID
190
+ game_data: 保存するゲームデータ
191
+
192
+ Returns:
193
+ 保存成功かどうか
194
+ """
195
+ try:
196
+ user_data = self._load_user_data()
197
+ if not user_data:
198
+ # ユーザーデータが存在しない場合は新規作成
199
+ user_data = {
200
+ "user_id": user_id,
201
+ "created_at": datetime.now().isoformat(),
202
+ "version": "1.0"
203
+ }
204
+
205
+ # ゲームデータを更新
206
+ user_data["game_data"] = game_data
207
+ user_data["last_access"] = datetime.now().isoformat()
208
+
209
+ with open(self.user_id_file, 'w', encoding='utf-8') as f:
210
+ json.dump(user_data, f, ensure_ascii=False, indent=2)
211
+
212
+ logger.info(f"ゲームデータを保存: {user_id[:8]}...")
213
+ return True
214
+
215
+ except Exception as e:
216
+ logger.error(f"ゲームデータ保存エラー: {e}")
217
+ return False
218
+
219
+ def load_game_data(self, user_id: str) -> Optional[Dict[str, Any]]:
220
+ """
221
+ ゲームデータを読み込み
222
+
223
+ Args:
224
+ user_id: ユーザーID
225
+
226
+ Returns:
227
+ ゲームデータ(存在しない場合はNone)
228
+ """
229
+ try:
230
+ user_data = self._load_user_data()
231
+ if user_data and user_data.get("user_id") == user_id:
232
+ game_data = user_data.get("game_data", {})
233
+ logger.info(f"ゲームデータを読み込み: {user_id[:8]}... (データサイズ: {len(str(game_data))}文字)")
234
+ return game_data
235
+ else:
236
+ logger.info(f"ゲームデータが見つかりません: {user_id[:8]}...")
237
+ return None
238
+
239
+ except Exception as e:
240
+ logger.error(f"ゲームデータ読み込みエラー: {e}")
241
+ return None