Skip to content

Commit 097e81b

Browse files
committed
core/messages: Add remove_from_disk
1 parent f3f5c6e commit 097e81b

File tree

3 files changed

+61
-52
lines changed

3 files changed

+61
-52
lines changed

openemail/core/messages.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from itertools import chain
1111
from json import JSONDecodeError
1212
from logging import getLogger
13+
from pathlib import Path
1314

1415
from . import client, crypto, data_dir, model, urls
1516
from .model import (
@@ -207,7 +208,11 @@ async def send(message: OutgoingMessage, /):
207208

208209

209210
async def delete(ident: str):
210-
"""Delete the message with `ident`."""
211+
"""Delete the message with `ident`.
212+
213+
Note that this will not delete children of the message,
214+
nor will it remove the message from disk. For that, see remove_from_disk().
215+
"""
211216
logger.debug("Deleting message %s…", ident[:_SHORT])
212217
for agent in await client.get_agents(client.user.address):
213218
if await client.request(
@@ -222,6 +227,20 @@ async def delete(ident: str):
222227
raise WriteError
223228

224229

230+
def remove_from_disk(message: Message):
231+
"""Remove `message` from disk if it has been downloaded before.
232+
233+
Note that this will not remove children of `message`.
234+
"""
235+
logger.debug("Removing message %s from disk…", message.ident[:_SHORT])
236+
host, local = message.author.host_part, message.author.local_part
237+
path = Path(host, local, "broadcasts" if message.is_broadcast else "")
238+
239+
(data_dir / "envelopes" / path / f"{message.ident}.json").unlink(missing_ok=True)
240+
(data_dir / "messages" / path / message.ident).unlink(True)
241+
logger.debug("Removed message %s from disk", message.ident[:_SHORT])
242+
243+
225244
async def _process_notification(
226245
notification: str, notifications: set[str]
227246
) -> Notification | None:

openemail/message.py

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@
77
from contextlib import suppress
88
from datetime import UTC, datetime
99
from gettext import ngettext
10-
from pathlib import Path
1110
from typing import Any, Self, cast, override
1211

1312
from gi.repository import Gdk, Gio, GLib, GObject, Gtk
1413

15-
from . import Notifier, Property, core, tasks
14+
from . import Notifier, Property, tasks
1615
from .core import client, messages, model
1716
from .core.model import Address, WriteError
1817
from .profile import Profile
@@ -255,14 +254,14 @@ class Message(GObject.Object):
255254
@Property(bool)
256255
def trashed(self) -> bool:
257256
"""Whether the item is in the trash."""
258-
from .store import settings
259-
260257
if self.can_discard or (not self._message):
261258
return False
262259

260+
from . import store
261+
263262
return any(
264263
msg.rsplit(maxsplit=1)[0] == self.unique_id
265-
for msg in settings.get_strv("trashed-messages")
264+
for msg in store.settings.get_strv("trashed-messages")
266265
)
267266

268267
def __init__(self, message: model.Message | None = None, **kwargs: Any):
@@ -380,12 +379,12 @@ def set_from_message(self, msg: model.Message | None, /):
380379

381380
def trash(self):
382381
"""Move `self` to the trash."""
383-
from .store import settings_add
384-
385382
if not self._message:
386383
return
387384

388-
settings_add(
385+
from . import store
386+
387+
store.settings_add(
389388
"trashed-messages",
390389
f"{self.unique_id} {datetime.now(UTC).date().isoformat()}",
391390
)
@@ -394,16 +393,16 @@ def trash(self):
394393

395394
def restore(self):
396395
"""Restore `self` from the trash."""
397-
from .store import settings
398-
399396
if not self._message:
400397
return
401398

402-
settings.set_strv(
399+
from . import store
400+
401+
store.settings.set_strv(
403402
"trashed-messages",
404403
tuple(
405404
msg
406-
for msg in settings.get_strv("trashed-messages")
405+
for msg in store.settings.get_strv("trashed-messages")
407406
if msg.rsplit(maxsplit=1)[0] != self.unique_id
408407
),
409408
)
@@ -412,34 +411,29 @@ def restore(self):
412411

413412
def delete(self):
414413
"""Remove `self` from the trash."""
415-
from .store import broadcasts, inbox, sent, settings_add
416-
417414
if not self._message:
418415
return
419416

420-
settings_add("deleted-messages", self.unique_id)
417+
from . import store
421418

422-
envelopes_dir = self._get_data_dir("envelopes", self._message)
423-
messages_dir = self._get_data_dir("messages", self._message)
419+
model = (
420+
store.sent
421+
if self._message.author == client.user.address
422+
else store.broadcasts
423+
if self._message.is_broadcast
424+
else store.inbox
425+
)
424426

425427
for child in self._message, *self._message.children:
426-
(envelopes_dir / f"{child.ident}.json").unlink(missing_ok=True)
427-
(messages_dir / child.ident).unlink(missing_ok=True)
428+
messages.remove_from_disk(child)
428429

429-
(
430-
sent
431-
if self._message.author == client.user.address
432-
else broadcasts
433-
if self._message.is_broadcast
434-
else inbox
435-
).remove(self.unique_id)
436-
self.restore()
430+
store.settings_add("deleted-messages", self.unique_id)
431+
model.remove(self.unique_id)
432+
self.restore() # Since it is deleted, there is no reason to keep it in trash
437433
self.set_from_message(None)
438434

439435
async def discard(self):
440436
"""Discard `self` and its children."""
441-
from .store import outbox, sent
442-
443437
if not self._message:
444438
return
445439

@@ -448,9 +442,11 @@ async def discard(self):
448442
Notifier.send(_("Cannot discard message while sending"))
449443
return
450444

451-
outbox.remove(ident := self.unique_id)
445+
from . import store
446+
447+
store.outbox.remove(ident := self.unique_id)
452448
with suppress(ValueError):
453-
sent.remove(ident)
449+
store.sent.remove(ident)
454450

455451
failed = False
456452
for msg in self._message, *self._message.children:
@@ -463,16 +459,14 @@ async def discard(self):
463459
failed = True
464460
continue
465461

466-
await outbox.update()
467-
await sent.update()
462+
await store.outbox.update()
463+
await store.sent.update()
468464

469465
def mark_read(self):
470466
"""Mark a message as read.
471467
472468
Does nothing if `message.new` is already `False`.
473469
"""
474-
from .store import settings_discard
475-
476470
if not self.new:
477471
return
478472

@@ -481,20 +475,16 @@ def mark_read(self):
481475
if not self._message:
482476
return
483477

478+
from . import store
479+
484480
self._message.new = False
485-
settings_discard("unread-messages", self.unique_id)
481+
store.settings_discard("unread-messages", self.unique_id)
486482

487483
def _update_trashed_state(self):
488484
self.can_trash = not (self.can_discard or self.trashed)
489485
self.can_reply = self.can_discard or self.can_trash
490486
self.notify("trashed")
491487

492-
@staticmethod
493-
def _get_data_dir(name: str, message: model.Message) -> Path:
494-
host, local = message.author.host_part, message.author.local_part
495-
suffix = "broadcasts" if message.is_broadcast else ""
496-
return core.data_dir / name / host / local / suffix
497-
498488

499489
async def send(
500490
readers: Iterable[Address],
@@ -511,8 +501,6 @@ async def send(
511501
512502
`attachments` is a dictionary of `Gio.File`s and filenames.
513503
"""
514-
from .store import outbox, sent
515-
516504
Notifier().sending = True
517505

518506
files = dict[model.AttachmentProperties, bytes]()
@@ -536,7 +524,9 @@ async def send(
536524
)
537525
] = data
538526

539-
outbox.add(
527+
from . import store
528+
529+
store.outbox.add(
540530
message := model.OutgoingMessage(
541531
readers=list(readers),
542532
subject=subject,
@@ -549,10 +539,10 @@ async def send(
549539
try:
550540
await messages.send(message)
551541
except WriteError:
552-
outbox.remove(message.ident)
542+
store.outbox.remove(message.ident)
553543
Notifier.send(_("Failed to send message"))
554544
Notifier().sending = False
555545
raise
556546

557-
sent.add(message)
547+
store.sent.add(message)
558548
Notifier().sending = False

openemail/profile.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,14 @@ def receive_broadcasts(self) -> bool:
169169

170170
@receive_broadcasts.setter
171171
def receive_broadcasts(self, receive_broadcasts: bool):
172-
from .store import broadcasts
172+
from . import store
173173

174174
if self._broadcasts == receive_broadcasts or (not self._profile):
175175
return
176176

177177
self._broadcasts = receive_broadcasts
178178

179-
tasks.create(broadcasts.update())
179+
tasks.create(store.broadcasts.update())
180180
tasks.create(
181181
contacts.new(
182182
self._profile.address,
@@ -224,9 +224,9 @@ def of(cls, user: Address | User, /) -> "Profile":
224224
"""
225225
match user:
226226
case Address():
227-
from .store import profiles
227+
from . import store
228228

229-
(profile := profiles[user]).address = user
229+
(profile := store.profiles[user]).address = user
230230
return profile
231231

232232
case User():

0 commit comments

Comments
 (0)