Coverage for functions \ flipdare \ mailer \ user \ flag_email.py: 83%

90 statements  

« 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# 

12 

13 

14from typing import override 

15from flipdare.mailer._jinja_email_template import JinjaEmailTemplate 

16from flipdare.mailer.app_email_params import AppEmailParams 

17from flipdare.mailer.app_email_type import AppEmailType 

18from flipdare.generated import RestrictionCategory, StopwatchDuration 

19from flipdare.generated.schema.email.body.user.flag_email_schema import FlagEmailSchema 

20from flipdare.wrapper import FlagWrapper, RestrictionWrapper, UserWrapper 

21 

22__all__ = ["FlagEmail"] 

23 

24 

25class FlagEmail(JinjaEmailTemplate[FlagEmailSchema]): 

26 

27 SCHEMA_CLASS = FlagEmailSchema 

28 

29 def __init__( 

30 self, 

31 flag: FlagWrapper, 

32 flagged_user: UserWrapper, 

33 restriction: RestrictionWrapper | None = None, 

34 ) -> None: 

35 data = self._build_data( 

36 flag=flag, 

37 flagged_user=flagged_user, 

38 restriction=restriction, 

39 ) 

40 email_type = AppEmailType.USR_FLAG_REVIEW 

41 super().__init__( 

42 data=data, 

43 params=AppEmailParams( 

44 email_type=email_type, 

45 schema=None, 

46 ), 

47 ) 

48 

49 def _build_data( 

50 self, 

51 flag: FlagWrapper, 

52 flagged_user: UserWrapper, 

53 restriction: RestrictionWrapper | None = None, 

54 ) -> FlagEmailSchema: 

55 

56 to_name = flagged_user.model.contact_name 

57 obj_id = flag.slug_code 

58 obj_label = flag.obj_type.label 

59 reason = flag.flag_type.label 

60 description = flag.description 

61 

62 is_banned = False 

63 is_suspended = False 

64 is_restricted = False 

65 is_being_reviewed = False 

66 is_warning = False 

67 

68 restriction_action = "" 

69 restriction_length = "" 

70 restriction_prefix = "" 

71 if restriction is not None: 

72 restrict_type = restriction.category 

73 if restrict_type == RestrictionCategory.ADMIN: 

74 is_being_reviewed = True 

75 elif restrict_type == RestrictionCategory.SUSPEND: 

76 is_suspended = True 

77 elif restrict_type == RestrictionCategory.WARN: 

78 is_warning = True 

79 

80 if restriction.duration == StopwatchDuration.PERMANENT: 

81 is_banned = True 

82 

83 is_restricted = True 

84 restriction_action = restriction.action.label 

85 restriction_length = restriction.duration.label 

86 restriction_prefix = restriction.duration.prefix 

87 

88 return FlagEmailSchema( 

89 { 

90 "to_name": to_name, 

91 "obj_id": obj_id, 

92 "obj_label": obj_label, 

93 "reason": reason, 

94 "description": description, 

95 "is_banned": is_banned, 

96 "is_suspended": is_suspended, 

97 "is_being_reviewed": is_being_reviewed, 

98 "is_warning": is_warning, 

99 "is_restricted": is_restricted, 

100 "restriction_action": restriction_action, 

101 "restriction_length": restriction_length, 

102 "restriction_prefix": restriction_prefix, 

103 }, 

104 ) 

105 

106 @override 

107 def newline_fields(self) -> list[str]: 

108 return ["reason", "description"] 

109 

110 @property 

111 @override 

112 def data(self) -> FlagEmailSchema: 

113 assert isinstance(self._data, dict) # narrowing, we known we have a dict.. 

114 return self._data 

115 

116 @property 

117 def to_name(self) -> str: 

118 return self.data["to_name"] 

119 

120 @property 

121 def obj_id(self) -> str: 

122 return self.data["obj_id"] 

123 

124 @property 

125 def obj_label(self) -> str: 

126 return self.data["obj_label"] 

127 

128 @property 

129 def reason(self) -> str: 

130 return self.data["reason"] 

131 

132 @property 

133 def is_restricted(self) -> bool: 

134 return self.data["is_restricted"] 

135 

136 @property 

137 def is_warning(self) -> bool: 

138 return self.data["is_warning"] 

139 

140 @property 

141 def is_banned(self) -> bool: 

142 return self.data["is_banned"] 

143 

144 @property 

145 def is_suspended(self) -> bool: 

146 return self.data["is_suspended"] 

147 

148 @property 

149 def is_being_reviewed(self) -> bool: 

150 return self.data["is_being_reviewed"] 

151 

152 @property 

153 def description(self) -> str: 

154 return self.data["description"] 

155 

156 @property 

157 def restriction_length(self) -> str: 

158 return self.data["restriction_length"] 

159 

160 @property 

161 def restriction_action(self) -> str: 

162 return self.data["restriction_action"] 

163 

164 @property 

165 def restriction_prefix(self) -> str: 

166 return self.data["restriction_prefix"]