Coverage for src/couchers/notifications/render.py: 84%

181 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-10-15 13:03 +0000

1import logging 

2from dataclasses import dataclass 

3 

4from couchers import urls 

5from couchers.notifications.unsubscribe import generate_unsub_topic_action 

6from couchers.templates.v2 import v2avatar, v2date, v2esc, v2phone, v2timestamp 

7 

8logger = logging.getLogger(__name__) 

9 

10 

11@dataclass(kw_only=True) 

12class RenderedNotification: 

13 # whether the notification is critical and cannot be turned off 

14 is_critical: bool = False 

15 # email subject 

16 email_subject: str 

17 # shows up when listing emails in many clients 

18 email_preview: str 

19 # corresponds to .mjml + .txt file in templates/v2 

20 email_template_name: str 

21 # other template args 

22 email_template_args: dict 

23 # the link label on the topic_action unsubscribe link 

24 email_topic_action_unsubscribe_text: str = None 

25 # the link label on the topic_key unsubscribe link 

26 email_topic_key_unsubscribe_text: str = None 

27 # url to unsubscribe with one click 

28 email_list_unsubscribe_url: str = None 

29 # push notification title 

30 push_title: str 

31 # push notification content 

32 push_body: str 

33 # url to an icon for push notifications 

34 push_icon: str 

35 # url to where clicking on the notification should take you 

36 push_url: str 

37 

38 

39def render_notification(user, notification) -> RenderedNotification: 

40 data = notification.topic_action.data_type.FromString(notification.data) 

41 if notification.topic == "host_request": 

42 view_link = urls.host_request(host_request_id=data.host_request.host_request_id) 

43 if notification.action == "missed_messages": 

44 their_your = "their" if data.am_host else "your" 

45 other = data.user 

46 # "declined your host request", or similar 

47 message = f"{other.name} sent you message(s) in {their_your} host request" 

48 return RenderedNotification( 

49 email_subject=message, 

50 email_preview=message, 

51 email_template_name="host_request__plain", 

52 email_template_args={ 

53 "view_link": view_link, 

54 "host_request": data.host_request, 

55 "message": message, 

56 "other": other, 

57 }, 

58 email_topic_action_unsubscribe_text="missed messages in host requests", 

59 push_title=message, 

60 push_body="Check the app for more info.", 

61 push_icon=v2avatar(other), 

62 push_url=view_link, 

63 ) 

64 elif notification.action in ["create", "message"]: 

65 if notification.action == "create": 

66 other = data.surfer 

67 message = f"{other.name} sent you a host request" 

68 topic_action_unsub_text = "new host requests" 

69 elif notification.action == "message": 

70 other = data.user 

71 if data.am_host: 

72 message = f"{other.name} sent you a message in their host request" 

73 else: 

74 message = f"{other.name} sent you a message in your host request" 

75 topic_action_unsub_text = "messages in host request" 

76 return RenderedNotification( 

77 email_subject=message, 

78 email_preview=message, 

79 email_template_name="host_request__message", 

80 email_template_args={ 

81 "view_link": view_link, 

82 "host_request": data.host_request, 

83 "message": message, 

84 "other": other, 

85 "text": data.text, 

86 }, 

87 email_topic_action_unsubscribe_text=topic_action_unsub_text, 

88 push_title=f"{message}", 

89 push_body=f"Dates: {v2date(data.host_request.from_date, user)} to {v2date(data.host_request.to_date, user)}.\n\n{data.text}", 

90 push_icon=v2avatar(other), 

91 push_url=view_link, 

92 ) 

93 elif notification.action in ["accept", "reject", "confirm", "cancel"]: 

94 if notification.action in ["accept", "reject"]: 

95 other = data.host 

96 their_your = "your" 

97 else: 

98 other = data.surfer 

99 their_your = "their" 

100 actioned = { 

101 "accept": "accepted", 

102 "reject": "declined", 

103 "confirm": "confirmed", 

104 "cancel": "cancelled", 

105 }[notification.action] 

106 # "declined your host request", or similar 

107 message = f"{other.name} {actioned} {their_your} host request" 

108 return RenderedNotification( 

109 email_subject=message, 

110 email_preview=message, 

111 email_template_name="host_request__plain", 

112 email_template_args={ 

113 "view_link": view_link, 

114 "host_request": data.host_request, 

115 "message": message, 

116 "other": other, 

117 }, 

118 email_topic_action_unsubscribe_text=f"{actioned} host requests", 

119 push_title=message, 

120 push_body="Check the app for more info.", 

121 push_icon=v2avatar(other), 

122 push_url=view_link, 

123 ) 

124 elif notification.topic_action.display == "password:change": 

125 title = "Your password was changed" 

126 message = "Your login password for Couchers.org was changed." 

127 return RenderedNotification( 

128 is_critical=True, 

129 email_subject=title, 

130 email_preview=message, 

131 email_template_name="security", 

132 email_template_args={ 

133 "title": title, 

134 "message": message, 

135 }, 

136 push_title=title, 

137 push_body=message, 

138 push_icon=urls.icon_url(), 

139 push_url=urls.account_settings_link(), 

140 ) 

141 elif notification.topic_action.display == "password_reset:start": 

142 message = "Someone initiated a password change on your account." 

143 return RenderedNotification( 

144 is_critical=True, 

145 email_subject="Reset your Couchers.org password", 

146 email_preview=message, 

147 email_template_name="password_reset", 

148 email_template_args={ 

149 "password_reset_link": urls.password_reset_link(password_reset_token=data.password_reset_token) 

150 }, 

151 push_title="A password reset was initiated on your account", 

152 push_body=message, 

153 push_icon=urls.icon_url(), 

154 push_url=urls.account_settings_link(), 

155 ) 

156 elif notification.topic_action.display == "password_reset:complete": 

157 title = "Your password was successfully reset" 

158 message = "Your password on Couchers.org was changed. If that was you, then no further action is needed." 

159 return RenderedNotification( 

160 is_critical=True, 

161 email_subject=title, 

162 email_preview=title, 

163 email_template_name="security", 

164 email_template_args={ 

165 "title": title, 

166 "message": message, 

167 }, 

168 push_title=title, 

169 push_body=message, 

170 push_icon=urls.icon_url(), 

171 push_url=urls.account_settings_link(), 

172 ) 

173 elif notification.topic_action.display == "email_address:change": 

174 title = "An email change was initiated on your account" 

175 message = f"An email change to the email <b>{data.new_email}</b> was initiated on your account." 

176 message_plain = f"An email change to the email {data.new_email} was initiated on your account." 

177 return RenderedNotification( 

178 is_critical=True, 

179 email_subject=title, 

180 email_preview=title, 

181 email_template_name="security", 

182 email_template_args={ 

183 "title": title, 

184 "message": message, 

185 }, 

186 push_title=title, 

187 push_body=message_plain, 

188 push_icon=urls.icon_url(), 

189 push_url=urls.account_settings_link(), 

190 ) 

191 elif notification.topic_action.display == "email_address:verify": 

192 title = "Email change completed" 

193 message = "Your new email address has been verified." 

194 return RenderedNotification( 

195 is_critical=True, 

196 email_subject=title, 

197 email_preview=message, 

198 email_template_name="security", 

199 email_template_args={ 

200 "title": title, 

201 "message": message, 

202 }, 

203 push_title=title, 

204 push_body=message, 

205 push_icon=urls.icon_url(), 

206 push_url=urls.account_settings_link(), 

207 ) 

208 elif notification.topic_action.display == "phone_number:change": 

209 title = "Phone verification started" 

210 message = f"You started phone number verification with the number <b>{v2phone(data.phone)}</b>." 

211 message_plain = f"You started phone number verification with the number {v2phone(data.phone)}." 

212 return RenderedNotification( 

213 is_critical=True, 

214 email_subject=title, 

215 email_preview=message, 

216 email_template_name="security", 

217 email_template_args={ 

218 "title": title, 

219 "message": message, 

220 }, 

221 push_title=title, 

222 push_body=message_plain, 

223 push_icon=urls.icon_url(), 

224 push_url=urls.feature_preview_link(), 

225 ) 

226 elif notification.topic_action.display == "phone_number:verify": 

227 title = "Phone successfully verified" 

228 message = f"Your phone was successfully verified as <b>{v2phone(data.phone)}</b> on Couchers.org." 

229 message_plain = f"Your phone was successfully verified as {v2phone(data.phone)} on Couchers.org." 

230 return RenderedNotification( 

231 is_critical=True, 

232 email_subject=title, 

233 email_preview=message_plain, 

234 email_template_name="security", 

235 email_template_args={ 

236 "title": title, 

237 "message": message, 

238 }, 

239 push_title=title, 

240 push_body=message_plain, 

241 push_icon=urls.icon_url(), 

242 push_url=urls.feature_preview_link(), 

243 ) 

244 elif notification.topic_action.display == "gender:change": 

245 title = "Your gender was changed" 

246 message = f"Your gender on Couchers.org was changed to <b>{data.gender}</b> by an admin." 

247 message_plain = f"Your gender on Couchers.org was changed to {data.gender} by an admin." 

248 return RenderedNotification( 

249 is_critical=True, 

250 email_subject=title, 

251 email_preview=message_plain, 

252 email_template_name="security", 

253 email_template_args={ 

254 "title": title, 

255 "message": message, 

256 }, 

257 push_title=title, 

258 push_body=message_plain, 

259 push_icon=urls.icon_url(), 

260 push_url=urls.account_settings_link(), 

261 ) 

262 elif notification.topic_action.display == "birthdate:change": 

263 title = "Your date of birth was changed" 

264 message = ( 

265 f"Your date of birth on Couchers.org was changed to <b>{v2date(data.birthdate, user)}</b> by an admin." 

266 ) 

267 message_plain = f"Your date of birth on Couchers.org was changed to {v2date(data.birthdate, user)} by an admin." 

268 return RenderedNotification( 

269 is_critical=True, 

270 email_subject=title, 

271 email_preview=message_plain, 

272 email_template_name="security", 

273 email_template_args={ 

274 "title": title, 

275 "message": message, 

276 }, 

277 push_title=title, 

278 push_body=message_plain, 

279 push_icon=urls.icon_url(), 

280 push_url=urls.account_settings_link(), 

281 ) 

282 elif notification.topic_action.display == "api_key:create": 

283 return RenderedNotification( 

284 is_critical=True, 

285 email_subject="Your API key for Couchers.org", 

286 email_preview="We have issued you an API key as per your request.", 

287 email_template_name="api_key", 

288 email_template_args={ 

289 "api_key": data.api_key, 

290 "expiry": data.expiry, 

291 }, 

292 push_title="An API key was created for your account", 

293 push_body="Details were sent to you via email.", 

294 push_icon=urls.icon_url(), 

295 push_url=urls.app_link(), 

296 ) 

297 elif notification.topic_action.display in ["badge:add", "badge:remove"]: 

298 actioned = "added to" if notification.action == "add" else "removed from" 

299 title = f"The {data.badge_name} badge was {actioned} your profile" 

300 return RenderedNotification( 

301 email_subject=title, 

302 email_preview=title, 

303 email_template_name="badge", 

304 email_template_args={ 

305 "badge_name": data.badge_name, 

306 "actioned": actioned, 

307 "unsub_type": "badge additions" if notification.action == "add" else "badge removals", 

308 }, 

309 email_topic_action_unsubscribe_text="badge additions" if notification.action == "add" else "badge removals", 

310 push_title=title, 

311 push_body=( 

312 "Check out your profile to see the new badge!" 

313 if notification.action == "add" 

314 else "You can see all your badges on your profile." 

315 ), 

316 push_icon=urls.icon_url(), 

317 push_url=urls.profile_link(), 

318 email_list_unsubscribe_url=generate_unsub_topic_action(notification), 

319 ) 

320 elif notification.topic_action.display == "donation:received": 

321 title = "Thank you for your donation to Couchers.org!" 

322 message = f"Thank you so much for your donation of ${data.amount} to Couchers.org." 

323 return RenderedNotification( 

324 is_critical=True, 

325 email_subject=title, 

326 email_preview=message, 

327 email_template_name="donation_received", 

328 email_template_args={ 

329 "amount": data.amount, 

330 "receipt_url": data.receipt_url, 

331 }, 

332 push_title=title, 

333 push_body=message, 

334 push_icon=urls.icon_url(), 

335 push_url=data.receipt_url, 

336 ) 

337 elif notification.topic_action.display == "friend_request:create": 

338 other = data.other_user 

339 preview = f"You've received a friend request from {other.name}" 

340 return RenderedNotification( 

341 email_subject=f"{other.name} wants to be your friend on Couchers.org!", 

342 email_preview=preview, 

343 email_template_name="friend_request", 

344 email_template_args={ 

345 "friend_requests_link": urls.friend_requests_link(), 

346 "other": other, 

347 }, 

348 email_topic_action_unsubscribe_text="new friend requests", 

349 push_title=f"{other.name} wants to be your friend", 

350 push_body=preview, 

351 push_icon=v2avatar(other), 

352 push_url=urls.friend_requests_link(), 

353 ) 

354 elif notification.topic_action.display == "friend_request:accept": 

355 other = data.other_user 

356 title = f"{other.name} accepted your friend request!" 

357 preview = f"{v2esc(other.name)} has accepted your friend request" 

358 return RenderedNotification( 

359 email_subject=title, 

360 email_preview=preview, 

361 email_template_name="friend_request_accepted", 

362 email_template_args={ 

363 "other_user_link": urls.user_link(username=other.username), 

364 "other": other, 

365 }, 

366 email_topic_action_unsubscribe_text="accepted friend requests", 

367 push_title=title, 

368 push_body=preview, 

369 push_icon=v2avatar(other), 

370 push_url=urls.user_link(username=other.username), 

371 ) 

372 elif notification.topic_action.display == "account_deletion:start": 

373 return RenderedNotification( 

374 is_critical=True, 

375 email_subject="Confirm your Couchers.org account deletion", 

376 email_preview="Please confirm that you want to delete your Couchers.org account.", 

377 email_template_name="account_deletion_start", 

378 email_template_args={ 

379 "deletion_link": urls.delete_account_link(account_deletion_token=data.deletion_token), 

380 }, 

381 push_title="Account deletion initiated", 

382 push_body="Someone initiated the deletion of your Couchers.org account. To delete your account, please follow the link in the email we sent you.", 

383 push_icon=urls.icon_url(), 

384 push_url=urls.app_link(), 

385 ) 

386 elif notification.topic_action.display == "account_deletion:complete": 

387 title = "Your Couchers.org account has been deleted" 

388 return RenderedNotification( 

389 is_critical=True, 

390 email_subject=title, 

391 email_preview="We have deleted your Couchers.org account, to undo, follow the link in this email.", 

392 email_template_name="account_deletion_complete", 

393 email_template_args={ 

394 "undelete_link": urls.recover_account_link(account_undelete_token=data.undelete_token), 

395 "days": data.undelete_days, 

396 }, 

397 push_title=title, 

398 push_body=f"You can still undo this by following the link we emailed to you within {data.undelete_days} days.", 

399 push_icon=urls.icon_url(), 

400 push_url=urls.app_link(), 

401 ) 

402 elif notification.topic_action.display == "account_deletion:recovered": 

403 title = "Your Couchers.org account has been recovered!" 

404 subtitle = "We have recovered your Couchers.org account as per your request! Welcome back!" 

405 return RenderedNotification( 

406 is_critical=True, 

407 email_subject=title, 

408 email_preview=subtitle, 

409 email_template_name="account_deletion_recovered", 

410 email_template_args={ 

411 "app_link": urls.app_link(), 

412 }, 

413 push_title=title, 

414 push_body=subtitle, 

415 push_icon=urls.icon_url(), 

416 push_url=urls.app_link(), 

417 ) 

418 elif notification.topic_action.display == "chat:message": 

419 return RenderedNotification( 

420 email_subject=data.message, 

421 email_preview="You received a message on Couchers.org!", 

422 email_template_name="chat_message", 

423 email_template_args={ 

424 "author": data.author, 

425 "message": data.message, 

426 "text": data.text, 

427 "view_link": urls.chat_link(chat_id=data.group_chat_id), 

428 }, 

429 email_topic_action_unsubscribe_text="new chat messages", 

430 email_topic_key_unsubscribe_text="this chat (mute)", 

431 push_title=data.message, 

432 push_body=data.text, 

433 push_icon=v2avatar(data.author), 

434 push_url=urls.chat_link(chat_id=data.group_chat_id), 

435 ) 

436 elif notification.topic_action.display == "chat:missed_messages": 

437 return RenderedNotification( 

438 email_subject="You have unseen messages on Couchers.org!", 

439 email_preview="You missed some messages on the platform.", 

440 email_template_name="chat_unseen_messages", 

441 email_template_args={ 

442 "items": [ 

443 { 

444 "author": item.author, 

445 "message": item.message, 

446 "text": item.text, 

447 "view_link": urls.chat_link(chat_id=item.group_chat_id), 

448 } 

449 for item in data.messages 

450 ] 

451 }, 

452 email_topic_action_unsubscribe_text="unseen chat messages", 

453 push_title="You have unseen messages on Couchers.org", 

454 push_body="Please check out any messages you missed.", 

455 push_icon=urls.icon_url(), 

456 push_url=urls.messages_link(), 

457 ) 

458 elif notification.topic == "event": 

459 event = data.event 

460 time_display = f"{v2timestamp(event.start_time, user)} - {v2timestamp(event.end_time, user)}" 

461 event_link = urls.event_link(occurrence_id=event.event_id, slug=event.slug) 

462 if notification.action in ["create_approved", "create_any"]: 

463 body = f"{time_display}\n" 

464 body += f"Invited by {data.inviting_user.name}\n\n" 

465 body += event.content 

466 community_link = ( 

467 urls.community_link(node_id=data.in_community.community_id, slug=data.in_community.slug) 

468 if data.in_community 

469 else None 

470 ) 

471 return RenderedNotification( 

472 email_subject=f'{data.inviting_user.name} invited you to "{event.title}"', 

473 email_preview="You've been invited to a new event on Couchers.org!", 

474 email_template_name="event_create", 

475 email_template_args={ 

476 "inviting_user": data.inviting_user, 

477 "time_display": time_display, 

478 "nearby": "nearby" if data.nearby else None, 

479 "community": data.in_community if data.in_community else None, 

480 "community_link": community_link, 

481 "nearby_or_community_text_plain": ( 

482 "nearby" if data.nearby else f"in the {data.in_community.name} community" 

483 ), 

484 "event": event, 

485 "view_link": event_link, 

486 }, 

487 email_topic_action_unsubscribe_text=( 

488 "new events by community members" 

489 if notification.action == "create_any" 

490 else "new events approved by moderators" 

491 ), 

492 push_title=f'{data.inviting_user.name} invited you to "{event.title}"', 

493 push_body=body, 

494 push_icon=v2avatar(data.inviting_user), 

495 push_url=event_link, 

496 ) 

497 elif notification.action == "update": 

498 updated_text = ", ".join(data.updated_items) 

499 body = f"{time_display}\n" 

500 body += f"{data.updating_user.name} updated: {updated_text}\n\n" 

501 body += event.content 

502 return RenderedNotification( 

503 email_subject=f'{data.updating_user.name} updated "{event.title}"', 

504 email_preview="An event you are subscribed to was updated.", 

505 email_template_name="event_update", 

506 email_template_args={ 

507 "updating_user": data.updating_user, 

508 "time_display": time_display, 

509 "event": event, 

510 "updated_text": updated_text, 

511 "view_link": event_link, 

512 }, 

513 email_topic_action_unsubscribe_text="event updates", 

514 push_title=f'{data.updating_user.name} updated "{event.title}"', 

515 push_body=body, 

516 push_icon=v2avatar(data.updating_user), 

517 push_url=event_link, 

518 ) 

519 elif notification.action == "cancel": 

520 body = f"{time_display}\n" 

521 body += f"The event has been cancelled by {data.cancelling_user.name}.\n\n" 

522 body += event.content 

523 return RenderedNotification( 

524 email_subject=f'{data.cancelling_user.name} cancelled "{event.title}"', 

525 email_preview="An event you are subscribed to has been cancelled.", 

526 email_template_name="event_cancel", 

527 email_template_args={ 

528 "cancelling_user": data.cancelling_user, 

529 "time_display": time_display, 

530 "event": event, 

531 "view_link": event_link, 

532 }, 

533 email_topic_action_unsubscribe_text="event cancellations", 

534 push_title=f'{data.cancelling_user.name} cancelled "{event.title}"', 

535 push_body=body, 

536 push_icon=v2avatar(data.cancelling_user), 

537 push_url=event_link, 

538 ) 

539 elif notification.action == "delete": 

540 return RenderedNotification( 

541 email_subject=f'A moderator deleted "{event.title}"', 

542 email_preview="An event you are subscribed to has been deleted.", 

543 email_template_name="event_delete", 

544 email_template_args={ 

545 "time_display": time_display, 

546 "event": event, 

547 }, 

548 email_topic_action_unsubscribe_text="event deletions", 

549 push_title=f'A moderator deleted "{event.title}"', 

550 push_body=f"{time_display}\nThe event has been deleted by the moderators.", 

551 push_icon=urls.icon_url(), 

552 push_url=urls.app_link(), 

553 ) 

554 elif notification.action == "invite_organizer": 

555 body = f"{time_display}\n" 

556 body += f"Invited to co-organize by {data.inviting_user.name}\n\n" 

557 body += event.content 

558 return RenderedNotification( 

559 email_subject=f'{data.inviting_user.name} invited you to co-organize "{event.title}"', 

560 email_preview="You were invited to co-organize an event on Couchers.org.", 

561 email_template_name="event_invite_organizer", 

562 email_template_args={ 

563 "inviting_user": data.inviting_user, 

564 "time_display": time_display, 

565 "event": event, 

566 "view_link": event_link, 

567 }, 

568 email_topic_action_unsubscribe_text="invitations to co-organize events", 

569 push_title=f'{data.inviting_user.name} invited you to co-organize "{event.title}"', 

570 push_body=body, 

571 push_icon=v2avatar(data.inviting_user), 

572 push_url=event_link, 

573 ) 

574 elif notification.topic == "reference": 

575 if notification.action == "receive_friend": 

576 title = f"You've received a friend reference from {data.from_user.name}!" 

577 return RenderedNotification( 

578 email_subject=title, 

579 email_preview=v2esc(data.text), 

580 email_template_name="friend_reference", 

581 email_template_args={ 

582 "from_user": data.from_user, 

583 "profile_references_link": urls.profile_references_link(), 

584 "text": data.text, 

585 }, 

586 email_topic_action_unsubscribe_text="new references from friends", 

587 push_title=title, 

588 push_body=data.text, 

589 push_icon=v2avatar(data.from_user), 

590 push_url=urls.profile_references_link(), 

591 ) 

592 elif notification.action in ["receive_hosted", "receive_surfed"]: 

593 title = f"You've received a reference from {data.from_user.name}!" 

594 # what was my type? i surfed with them if i received a "hosted" request 

595 surfed = (notification.action == "receive_hosted",) 

596 leave_reference_link = urls.leave_reference_link( 

597 reference_type="surfed" if surfed else "hosted", 

598 to_user_id=data.from_user.user_id, 

599 host_request_id=data.host_request_id, 

600 ) 

601 profile_references_link = urls.profile_references_link() 

602 if data.text: 

603 body = v2esc(data.text) 

604 push_url = profile_references_link 

605 else: 

606 body = "Please go and write a reference for them too. It's a nice gesture and helps us build a community together!" 

607 push_url = leave_reference_link 

608 return RenderedNotification( 

609 email_subject=title, 

610 email_preview=body, 

611 email_template_name="host_reference", 

612 email_template_args={ 

613 "from_user": data.from_user, 

614 "leave_reference_link": leave_reference_link, 

615 "profile_references_link": profile_references_link, 

616 "text": data.text, 

617 "both_written": True if data.text else False, 

618 "surfed": surfed, 

619 }, 

620 email_topic_action_unsubscribe_text="new references from " + ("hosts" if surfed else "surfers"), 

621 push_title=title, 

622 push_body=body, 

623 push_icon=v2avatar(data.from_user), 

624 push_url=push_url, 

625 ) 

626 elif notification.action in ["reminder_hosted", "reminder_surfed"]: 

627 # what was my type? i surfed with them if i get a surfed reminder 

628 surfed = (notification.action == "reminder_surfed",) 

629 leave_reference_link = urls.leave_reference_link( 

630 reference_type="surfed" if surfed else "hosted", 

631 to_user_id=data.other_user.user_id, 

632 host_request_id=data.host_request_id, 

633 ) 

634 title = f"You have {data.days_left} days to write a reference for {data.other_user.name}!" 

635 preview = "It's a nice gesture to write references and helps us build a community together! References will become visible 2 weeks after the stay, or when you've both written a reference for each other, whichever happens first." 

636 return RenderedNotification( 

637 email_subject=title, 

638 email_preview=preview, 

639 email_template_name="reference_reminder", 

640 email_template_args={ 

641 "other_user": data.other_user, 

642 "leave_reference_link": leave_reference_link, 

643 "days_left": str(data.days_left), 

644 "surfed": surfed, 

645 }, 

646 email_topic_action_unsubscribe_text=("surfed" if surfed else "hosted") + " reference reminders", 

647 push_title=title, 

648 push_body=preview, 

649 push_icon=v2avatar(data.other_user), 

650 push_url=leave_reference_link, 

651 ) 

652 elif notification.topic_action.display == "onboarding:reminder": 

653 if notification.key == "1": 

654 return RenderedNotification( 

655 email_subject="Welcome to Couchers.org and the future of couch surfing", 

656 email_preview="We are so excited to have you join our community!", 

657 email_template_name="onboarding1", 

658 email_template_args={ 

659 "app_link": urls.app_link(), 

660 "edit_profile_link": urls.edit_profile_link(), 

661 }, 

662 email_topic_action_unsubscribe_text="onboarding emails", 

663 push_title="Welcome to Couchers.org and the future of couch surfing", 

664 push_body=f"Hi {v2esc(user.name)}! We are excited that you have joined us! Please take a moment to complete your profile with a picture and a bit of text about yourself!", 

665 push_icon=urls.icon_url(), 

666 push_url=urls.edit_profile_link(), 

667 ) 

668 elif notification.key == "2": 

669 return RenderedNotification( 

670 email_subject="Complete your profile on Couchers.org", 

671 email_preview="We would ask one big favour of you: please fill out your profile by adding a photo and some text.", 

672 email_template_name="onboarding2", 

673 email_template_args={ 

674 "edit_profile_link": urls.edit_profile_link(), 

675 }, 

676 email_topic_action_unsubscribe_text="onboarding emails", 

677 push_title="Please complete your profile on Couchers.org!", 

678 push_body=f"Hi {v2esc(user.name)}! We would ask one big favour of you: please fill out your profile by adding a photo and some text.", 

679 push_icon=urls.icon_url(), 

680 push_url=urls.edit_profile_link(), 

681 ) 

682 elif notification.topic_action.display == "modnote:create": 

683 title = "You have received a mod note" 

684 message = "You have received an important note from the moderators. You must read and acknowledge it before continuing to use the platform." 

685 return RenderedNotification( 

686 is_critical=True, 

687 email_subject=title, 

688 email_preview=message, 

689 email_template_name="mod_note", 

690 email_template_args={"title": title}, 

691 push_title="You received a mod note", 

692 push_body="You need to read and acknowledge the note before continuing to use the platform.", 

693 push_icon=urls.icon_url(), 

694 push_url=urls.app_link(), 

695 ) 

696 else: 

697 raise NotImplementedError(f"Unknown topic-action: {notification.topic}:{notification.action}")