Coverage for functions \ flipdare \ mailer \ user \ dared_email.py: 74%
87 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
1#!/usr/bin/env python
2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved.
3#
4# This file is part of Flipdare's proprietary software and contains
5# confidential and copyrighted material. Unauthorised copying,
6# modification, distribution, or use of this file is strictly
7# prohibited without prior written permission from Flipdare Pty Ltd.
8#
9# This software includes third-party components licensed under MIT,
10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details.
11#
14from enum import StrEnum
15from typing import Any, Self, override
16from flipdare.mailer._jinja_email_template import JinjaEmailTemplate
17from flipdare.mailer.app_email_params import AppEmailParams
18from flipdare.mailer.app_email_type import AppEmailType
19from flipdare.generated.schema.email.body.user.dared_email_schema import DaredEmailSchema
20from flipdare.generated.schema.email.subject.user.dare_subject_schema import DareSubjectSchema
21from flipdare.generated.schema.email.subject.user.group_dare_subject_schema import (
22 GroupDareSubjectSchema,
23)
24from flipdare.generated.shared.app_deep_link import AppDeepLink
25from flipdare.wrapper import DareWrapper, UserWrapper
27__all__ = ["DaredEmail"]
30class DaredEmailType(StrEnum):
31 CREATE = "creation"
32 RESPONSE = "response"
33 COMPLETE = "complete"
35 @property
36 def is_complete(self) -> bool:
37 return self == DaredEmailType.COMPLETE
39 @property
40 def is_response(self) -> bool:
41 return self == DaredEmailType.RESPONSE
44class DaredEmail(JinjaEmailTemplate[DaredEmailSchema]):
46 SCHEMA_CLASS = DaredEmailSchema
48 def __init__(self, data: DaredEmailSchema, params: AppEmailParams[Any]) -> None:
49 super().__init__(
50 data=data,
51 params=params,
52 )
54 @classmethod
55 def group_dare(
56 cls,
57 dare: DareWrapper,
58 to_user: UserWrapper,
59 from_user: UserWrapper,
60 group_name: str,
61 dared_email_type: DaredEmailType,
62 ) -> Self:
63 from_model = from_user.model
64 to_model = to_user.model
65 is_complete = dared_email_type.is_complete
67 to_name = from_model.contact_name if is_complete else to_model.contact_name
69 email_type: AppEmailType
70 match dared_email_type:
71 case DaredEmailType.COMPLETE:
72 email_type = AppEmailType.USR_GROUP_DARED_COMPLETE
73 case DaredEmailType.RESPONSE:
74 email_type = AppEmailType.USR_GROUP_DARED_RESPONSE
75 case DaredEmailType.CREATE:
76 email_type = AppEmailType.USR_GROUP_DARED
78 data = cls._build_data(
79 dare=dare,
80 to_name=to_name,
81 name=group_name,
82 dared_email_type=dared_email_type,
83 )
85 ctx = GroupDareSubjectSchema(
86 name=group_name,
87 group_name=group_name,
88 )
90 return cls(
91 data=data,
92 params=AppEmailParams(
93 email_type=email_type,
94 schema=ctx,
95 ),
96 )
98 @classmethod
99 def dare(
100 cls,
101 dare: DareWrapper,
102 to_user: UserWrapper,
103 from_user: UserWrapper,
104 dared_email_type: DaredEmailType,
105 ) -> Self:
106 is_complete = dared_email_type.is_complete
108 to_name = from_user.contact_name if is_complete else to_user.contact_name
109 name = to_user.contact_name if is_complete else from_user.contact_name
111 email_type: AppEmailType
112 match dared_email_type:
113 case DaredEmailType.COMPLETE:
114 email_type = AppEmailType.USR_DARED_COMPLETE
115 case DaredEmailType.RESPONSE:
116 email_type = AppEmailType.USR_DARED_RESPONSE
117 case DaredEmailType.CREATE:
118 email_type = AppEmailType.USR_DARED
120 ctx = DareSubjectSchema(
121 name=name,
122 dare_name=dare.short_description,
123 )
125 data = cls._build_data(
126 dare=dare,
127 to_name=to_name,
128 name=name,
129 dared_email_type=dared_email_type,
130 )
132 return cls(
133 data=data,
134 params=AppEmailParams(
135 email_type=email_type,
136 schema=ctx,
137 ),
138 )
140 @staticmethod
141 def _build_data(
142 dare: DareWrapper,
143 to_name: str,
144 name: str,
145 dared_email_type: DaredEmailType,
146 ) -> DaredEmailSchema:
147 message: str = dare.message
148 app_link = AppDeepLink.DARE.app_link(dare.doc_id)
150 return DaredEmailSchema(
151 {
152 "to_name": to_name,
153 "name": name,
154 "is_response": dared_email_type.is_response,
155 "is_complete": dared_email_type.is_complete,
156 "message": message,
157 "app_link": app_link,
158 },
159 )
161 @override
162 def newline_fields(self) -> list[str]:
163 return ["message"]
165 @property
166 @override
167 def data(self) -> DaredEmailSchema:
168 assert isinstance(self._data, dict) # narrowing, we known we have a dict..
169 return self._data
171 @property
172 def is_complete(self) -> bool:
173 return self.data["is_complete"]
175 @property
176 def is_response(self) -> bool:
177 return self.data["is_response"]
179 @property
180 def app_link(self) -> str:
181 return self.data["app_link"]
183 @property
184 def to_name(self) -> str:
185 return self.data["to_name"]
187 @property
188 def name(self) -> str:
189 return self.data["name"]
191 @property
192 def message(self) -> str:
193 return self.data["message"]