BasitAliii commited on
Commit
bb83c5b
·
verified ·
1 Parent(s): d675e08

Update storage.py

Browse files
Files changed (1) hide show
  1. storage.py +83 -6
storage.py CHANGED
@@ -1,10 +1,14 @@
1
  from dataclasses import dataclass, asdict
2
- from typing import List, Dict, Any, Optional
3
  import uuid
4
-
 
 
5
  from utils import normalize_skill_list
6
 
7
-
 
 
8
  @dataclass
9
  class Profile:
10
  id: str
@@ -20,8 +24,6 @@ class Profile:
20
  return Profile(
21
  id=str(d.get("id") or uuid.uuid4()),
22
  username=str(d.get("username") or "").strip(),
23
-
24
- # ✅ CRITICAL FIX
25
  offers=normalize_skill_list(
26
  ",".join(d.get("offers", []))
27
  if isinstance(d.get("offers"), list)
@@ -32,7 +34,6 @@ class Profile:
32
  if isinstance(d.get("wants"), list)
33
  else d.get("wants")
34
  ),
35
-
36
  availability=str(d.get("availability") or ""),
37
  preferences=str(d.get("preferences") or ""),
38
  avatar=d.get("avatar"),
@@ -40,3 +41,79 @@ class Profile:
40
 
41
  def to_dict(self) -> Dict[str, Any]:
42
  return asdict(self)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from dataclasses import dataclass, asdict
2
+ from typing import List, Dict, Any, Optional, Tuple
3
  import uuid
4
+ import json
5
+ from pathlib import Path
6
+ from config import DATA_FILE
7
  from utils import normalize_skill_list
8
 
9
+ # -----------------------------
10
+ # Profile Data Class
11
+ # -----------------------------
12
  @dataclass
13
  class Profile:
14
  id: str
 
24
  return Profile(
25
  id=str(d.get("id") or uuid.uuid4()),
26
  username=str(d.get("username") or "").strip(),
 
 
27
  offers=normalize_skill_list(
28
  ",".join(d.get("offers", []))
29
  if isinstance(d.get("offers"), list)
 
34
  if isinstance(d.get("wants"), list)
35
  else d.get("wants")
36
  ),
 
37
  availability=str(d.get("availability") or ""),
38
  preferences=str(d.get("preferences") or ""),
39
  avatar=d.get("avatar"),
 
41
 
42
  def to_dict(self) -> Dict[str, Any]:
43
  return asdict(self)
44
+
45
+ # -----------------------------
46
+ # ProfileStore
47
+ # -----------------------------
48
+ class ProfileStore:
49
+ def __init__(self, path: Path = DATA_FILE) -> None:
50
+ self.path = path
51
+ self._ensure_file()
52
+
53
+ def _ensure_file(self) -> None:
54
+ if not self.path.exists():
55
+ self.path.write_text("[]", encoding="utf-8")
56
+
57
+ def load_all(self) -> List[Profile]:
58
+ try:
59
+ data = json.loads(self.path.read_text(encoding="utf-8"))
60
+ return [Profile.from_dict(d) for d in data if isinstance(d, dict)]
61
+ except json.JSONDecodeError:
62
+ return []
63
+
64
+ def save_all(self, profiles: List[Profile]) -> None:
65
+ self.path.write_text(
66
+ json.dumps([p.to_dict() for p in profiles], indent=2, ensure_ascii=False),
67
+ encoding="utf-8",
68
+ )
69
+
70
+ def find_by_username(self, username: str) -> Optional[Profile]:
71
+ username = (username or "").strip()
72
+ for p in self.load_all():
73
+ if p.username.lower() == username.lower():
74
+ return p
75
+ return None
76
+
77
+ def add_or_update(self, profile: Profile) -> Tuple[bool, str]:
78
+ ok, err = self.validate_profile(profile)
79
+ if not ok:
80
+ return False, f"Validation failed: {err}"
81
+
82
+ profiles = self.load_all()
83
+ existing = next((p for p in profiles if p.username.lower() == profile.username.lower()), None)
84
+
85
+ if existing:
86
+ existing.offers = profile.offers
87
+ existing.wants = profile.wants
88
+ existing.availability = profile.availability
89
+ existing.preferences = profile.preferences
90
+ existing.avatar = profile.avatar
91
+ self.save_all(profiles)
92
+ return True, "Profile updated."
93
+
94
+ profile.id = profile.id or str(uuid.uuid4())
95
+ profiles.append(profile)
96
+ self.save_all(profiles)
97
+ return True, "Profile created."
98
+
99
+ def delete(self, username: str) -> Tuple[bool, str]:
100
+ username = (username or "").strip()
101
+ profiles = self.load_all()
102
+ profiles_new = [p for p in profiles if p.username.lower() != username.lower()]
103
+ if len(profiles_new) == len(profiles):
104
+ return False, "Profile not found."
105
+ self.save_all(profiles_new)
106
+ return True, "Profile deleted."
107
+
108
+ @staticmethod
109
+ def validate_profile(profile: Profile) -> Tuple[bool, Optional[str]]:
110
+ if not profile.username:
111
+ return False, "Username is required."
112
+ if len(profile.username) > 60:
113
+ return False, "Username must be 60 characters or fewer."
114
+ if not profile.offers and not profile.wants:
115
+ return False, "At least one offer or want is required."
116
+ for s in profile.offers + profile.wants:
117
+ if not s or len(s) > 120:
118
+ return False, "Invalid skill entry."
119
+ return True, None