meetnote 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,198 @@
1
+ from datetime import datetime, timezone
2
+ from pathlib import Path
3
+ from typing import cast
4
+
5
+ from meetnote.domain.models import (
6
+ ActionItem,
7
+ ActionItemStatus,
8
+ Meeting,
9
+ )
10
+ from meetnote.storage.database import connect
11
+
12
+
13
+ def meeting_from_row(row: dict) -> Meeting:
14
+ return Meeting(
15
+ id=int(row["id"]),
16
+ title=str(row["title"]),
17
+ notes=str(row["notes"]),
18
+ transcript=str(row["transcript"]),
19
+ created_at=str(row["created_at"]),
20
+ )
21
+
22
+
23
+ def action_item_from_row(row: dict) -> ActionItem:
24
+ return ActionItem(
25
+ id=int(row["id"]),
26
+ meeting_id=int(row["meeting_id"]),
27
+ description=str(row["description"]),
28
+ owner=str(row["owner"]) if row["owner"] is not None else None,
29
+ status=cast(ActionItemStatus, row["status"]),
30
+ due_date=(str(row["due_date"]) if row["due_date"] is not None else None),
31
+ )
32
+
33
+
34
+ class MeetingRepository:
35
+ def __init__(self, database_path: Path) -> None:
36
+ self.database_path = database_path
37
+
38
+ def create(self, title: str, notes: str = "") -> int:
39
+ created_at = datetime.now(timezone.utc).isoformat()
40
+
41
+ with connect(self.database_path) as connection:
42
+ cursor = connection.execute(
43
+ """
44
+ INSERT INTO meetings (title, notes, created_at)
45
+ VALUES (?, ?, ?)
46
+ """,
47
+ (title, notes, created_at),
48
+ )
49
+
50
+ if cursor.lastrowid is None:
51
+ raise RuntimeError("Meeting insert did not return an ID")
52
+
53
+ return cursor.lastrowid
54
+
55
+ def get(self, meeting_id: int) -> Meeting | None:
56
+ with connect(self.database_path) as connection:
57
+ row = connection.execute(
58
+ """
59
+ SELECT id, title, notes, transcript, created_at
60
+ FROM meetings
61
+ WHERE id = ?
62
+ """,
63
+ (meeting_id,),
64
+ ).fetchone()
65
+
66
+ return meeting_from_row(dict(row)) if row is not None else None
67
+
68
+ def list_all(self) -> list[Meeting]:
69
+ with connect(self.database_path) as connection:
70
+ rows = connection.execute(
71
+ """
72
+ SELECT id, title, notes, transcript, created_at
73
+ FROM meetings
74
+ ORDER BY created_at DESC
75
+ """
76
+ ).fetchall()
77
+
78
+ return [meeting_from_row(dict(row)) for row in rows]
79
+
80
+ def delete(self, meeting_id: int) -> None:
81
+ with connect(self.database_path) as connection:
82
+ connection.execute(
83
+ """
84
+ DELETE FROM meetings
85
+ WHERE id = ?
86
+ """,
87
+ (meeting_id,),
88
+ )
89
+
90
+ def update_transcript(
91
+ self,
92
+ meeting_id: int,
93
+ transcript: str,
94
+ ) -> None:
95
+ with connect(self.database_path) as connection:
96
+ connection.execute(
97
+ """
98
+ UPDATE meetings
99
+ SET transcript = ?
100
+ WHERE id = ?
101
+ """,
102
+ (transcript, meeting_id),
103
+ )
104
+
105
+
106
+ class ActionItemRepository:
107
+ def __init__(self, database_path: Path) -> None:
108
+ self.database_path = database_path
109
+
110
+ def create(
111
+ self,
112
+ meeting_id: int,
113
+ description: str,
114
+ owner: str | None = None,
115
+ due_date: str | None = None,
116
+ ) -> int:
117
+ with connect(self.database_path) as connection:
118
+ cursor = connection.execute(
119
+ """
120
+ INSERT INTO action_items
121
+ (meeting_id, description, owner, due_date)
122
+ VALUES (?, ?, ?, ?)
123
+ """,
124
+ (meeting_id, description, owner, due_date),
125
+ )
126
+
127
+ if cursor.lastrowid is None:
128
+ raise RuntimeError("Action-item insert did not return an ID")
129
+
130
+ return cursor.lastrowid
131
+
132
+ def list_for_meeting(self, meeting_id: int) -> list[ActionItem]:
133
+ with connect(self.database_path) as connection:
134
+ rows = connection.execute(
135
+ """
136
+ SELECT id, meeting_id, description, owner, status, due_date
137
+ FROM action_items
138
+ WHERE meeting_id = ?
139
+ ORDER BY id
140
+ """,
141
+ (meeting_id,),
142
+ ).fetchall()
143
+
144
+ return [action_item_from_row(dict(row)) for row in rows]
145
+
146
+ def mark_done(self, action_item_id: int) -> None:
147
+ with connect(self.database_path) as connection:
148
+ connection.execute(
149
+ """
150
+ UPDATE action_items
151
+ SET status = 'done'
152
+ WHERE id = ?
153
+ """,
154
+ (action_item_id,),
155
+ )
156
+
157
+ def mark_open(self, action_item_id: int) -> None:
158
+ with connect(self.database_path) as connection:
159
+ connection.execute(
160
+ """
161
+ UPDATE action_items
162
+ SET status = 'open'
163
+ WHERE id = ?
164
+ """,
165
+ (action_item_id,),
166
+ )
167
+
168
+ def delete(self, action_item_id: int) -> None:
169
+ with connect(self.database_path) as connection:
170
+ connection.execute(
171
+ """
172
+ DELETE FROM action_items
173
+ WHERE id = ?
174
+ """,
175
+ (action_item_id,),
176
+ )
177
+
178
+ def verify(self, action_item_id: int) -> None:
179
+ with connect(self.database_path) as connection:
180
+ connection.execute(
181
+ """
182
+ UPDATE action_items
183
+ SET status = 'verified'
184
+ WHERE id = ?
185
+ """,
186
+ (action_item_id,),
187
+ )
188
+
189
+ def reopen(self, action_item_id: int) -> None:
190
+ with connect(self.database_path) as connection:
191
+ connection.execute(
192
+ """
193
+ UPDATE action_items
194
+ SET status = 'open'
195
+ WHERE id = ?
196
+ """,
197
+ (action_item_id,),
198
+ )
File without changes