Files
vrobbler/vrobbler/apps/tasks/models.py

108 lines
3.1 KiB
Python

from dataclasses import dataclass
from typing import Optional
from django.apps import apps
from django.db import models
from django.urls import reverse
from scrobbles.dataclasses import BaseLogData
from scrobbles.mixins import LongPlayScrobblableMixin, ScrobblableConstants
BNULL = {"blank": True, "null": True}
TODOIST_TASK_URL = "https://app.todoist.com/app/task/{id}"
@dataclass
class TaskLogData(BaseLogData):
title: Optional[str] = None
labels: Optional[list[str]] = None
orgmode_id: Optional[str] = None
orgmode_state: Optional[str] = None
orgmode_properties: Optional[dict] = None
orgmode_drawers: Optional[list] = None
orgmode_timestamps: Optional[list] = None
todoist_id: Optional[str] = None
todoist_project_id: Optional[str] = None
_excluded_fields = {
"labels",
"orgmode_id",
"orgmode_state",
"orgmode_properties",
"orgmode_drawers",
"orgmode_timestamps",
"todoist_id",
"todoist_project_id",
}
def notes_as_str(self) -> str:
"""Return formatted notes with line breaks and no keys"""
labels_str = ""
if self.labels:
labels_str = ", ".join(self.labels)
lines = []
if self.notes:
for note in self.notes:
if isinstance(note, dict):
timestamp, note_text = next(iter(note.items()))
# Flatten newlines and clean whitespace
note_text = " ".join(note_text.strip().split())
lines.append(f"{timestamp}: {note_text} [{labels_str}]")
if isinstance(note, str):
lines.append(note)
return "\n".join(lines)
class Task(LongPlayScrobblableMixin):
"""Basically a holder for Todoist Tasks
and any other otherwise generic tasks.
"""
description = models.TextField(**BNULL)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("tasks:task_detail", kwargs={"slug": self.uuid})
@property
def strings(self) -> ScrobblableConstants:
return ScrobblableConstants(verb="Doing", tags="memo")
@property
def logdata_cls(self):
return TaskLogData
def source_url_for_user(self, user_id) -> str:
url = ""
scrobble = self.scrobbles(user_id).first()
if scrobble:
if scrobble.log.get("source") == "todoist":
url = TODOIST_TASK_URL.format(id=scrobble.logdata.todist_id)
return url
def subtitle_for_user(self, user_id):
scrobble = self.scrobbles(user_id).first()
return scrobble.logdata.title or scrobble.log.get("title")
@classmethod
def find_or_create(cls, title: str) -> "Task":
task, created = cls.objects.get_or_create(title=title)
if created:
task.base_run_time_seconds = 1800
task.save(update_fields=["base_run_time_seconds"])
return task
def scrobbles(self, user_id):
Scrobble = apps.get_model("scrobbles", "Scrobble")
return Scrobble.objects.filter(user_id=user_id, task=self).order_by(
"-timestamp"
)