email_notification.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package email
  2. import (
  3. "fmt"
  4. "strconv"
  5. "github.com/avct/uasurfer"
  6. "github.com/ente-io/museum/pkg/controller/lock"
  7. "github.com/ente-io/museum/pkg/repo"
  8. "github.com/ente-io/museum/pkg/utils/email"
  9. "github.com/ente-io/museum/pkg/utils/time"
  10. log "github.com/sirupsen/logrus"
  11. )
  12. const (
  13. WebAppFirstUploadTemplate = "web_app_first_upload.html"
  14. MobileAppFirstUploadTemplate = "mobile_app_first_upload.html"
  15. FirstUploadEmailSubject = "Congratulations! 🎉"
  16. StorageLimitExceededMailLock = "storage_limit_exceeded_mail_lock"
  17. StorageLimitExceededTemplateID = "storage_limit_exceeded"
  18. StorageLimitExceededTemplate = "storage_limit_exceeded.html"
  19. FilesCollectedTemplate = "files_collected.html"
  20. FilesCollectedTemplateID = "files_collected"
  21. FilesCollectedSubject = "You've got photos!"
  22. SubscriptionUpgradedTemplate = "subscription_upgraded.html"
  23. SubscriptionUpgradedSubject = "Thank you for choosing ente!"
  24. FilesCollectedMuteDurationInMinutes = 10
  25. StorageLimitExceededSubject = "[Alert] You have exceeded your storage limit"
  26. ReferralSuccessfulTemplate = "successful_referral.html"
  27. ReferralSuccessfulSubject = "You've earned 10 GB on ente! 🎁"
  28. )
  29. type EmailNotificationController struct {
  30. UserRepo *repo.UserRepository
  31. LockController *lock.LockController
  32. NotificationHistoryRepo *repo.NotificationHistoryRepository
  33. isSendingStorageLimitExceededMails bool
  34. }
  35. func (c *EmailNotificationController) OnFirstFileUpload(userID int64, userAgent string) {
  36. user, err := c.UserRepo.Get(userID)
  37. if err != nil {
  38. return
  39. }
  40. os := getOSFromUA(userAgent)
  41. template := WebAppFirstUploadTemplate
  42. if os == uasurfer.OSAndroid || os == uasurfer.OSiOS {
  43. template = MobileAppFirstUploadTemplate
  44. }
  45. err = email.SendTemplatedEmail([]string{user.Email}, "team@ente.io", "team@ente.io", FirstUploadEmailSubject, template, nil, nil)
  46. if err != nil {
  47. log.Error("Error sending first upload email ", err)
  48. }
  49. }
  50. func getOSFromUA(ua string) uasurfer.OSName {
  51. return uasurfer.Parse(ua).OS.Name
  52. }
  53. func (c *EmailNotificationController) OnSuccessfulReferral(userID int64) {
  54. user, err := c.UserRepo.Get(userID)
  55. if err != nil {
  56. return
  57. }
  58. err = email.SendTemplatedEmail([]string{user.Email}, "team@ente.io", "team@ente.io", ReferralSuccessfulSubject, ReferralSuccessfulTemplate, nil, nil)
  59. if err != nil {
  60. log.Error("Error sending first upload email ", err)
  61. }
  62. }
  63. func (c *EmailNotificationController) OnFilesCollected(userID int64) {
  64. user, err := c.UserRepo.Get(userID)
  65. if err != nil {
  66. return
  67. }
  68. lastNotificationTime, err := c.NotificationHistoryRepo.GetLastNotificationTime(userID, FilesCollectedTemplateID)
  69. logger := log.WithFields(log.Fields{
  70. "user_id": userID,
  71. })
  72. if err != nil {
  73. logger.Error("Could not fetch last notification time", err)
  74. return
  75. }
  76. if lastNotificationTime > time.MicrosecondsAfterMinutes(-FilesCollectedMuteDurationInMinutes) {
  77. logger.Info("Not notifying user about a collected file")
  78. return
  79. }
  80. lockName := "files_collected_" + strconv.FormatInt(userID, 10)
  81. lockStatus := c.LockController.TryLock(lockName, time.MicrosecondsAfterMinutes(FilesCollectedMuteDurationInMinutes))
  82. if !lockStatus {
  83. log.Error("Could not acquire lock to send file collected mails")
  84. return
  85. }
  86. defer c.LockController.ReleaseLock(lockName)
  87. logger.Info("Notifying about files collected")
  88. err = email.SendTemplatedEmail([]string{user.Email}, "team@ente.io", "team@ente.io", FilesCollectedSubject, FilesCollectedTemplate, nil, nil)
  89. if err != nil {
  90. log.Error("Error sending files collected email ", err)
  91. }
  92. c.NotificationHistoryRepo.SetLastNotificationTimeToNow(userID, FilesCollectedTemplateID)
  93. }
  94. func (c *EmailNotificationController) OnAccountUpgrade(userID int64) {
  95. user, err := c.UserRepo.Get(userID)
  96. if err != nil {
  97. log.Error("Could not find user to email", err)
  98. return
  99. }
  100. log.Info(fmt.Sprintf("Emailing on account upgrade %d", user.ID))
  101. err = email.SendTemplatedEmail([]string{user.Email}, "team@ente.io", "team@ente.io", SubscriptionUpgradedSubject, SubscriptionUpgradedTemplate, nil, nil)
  102. if err != nil {
  103. log.Error("Error sending files collected email ", err)
  104. }
  105. }
  106. func (c *EmailNotificationController) SendStorageLimitExceededMails() {
  107. if c.isSendingStorageLimitExceededMails {
  108. log.Info("Skipping sending storage limit exceeded mails as another instance is still running")
  109. return
  110. }
  111. c.setStorageLimitExceededMailerJobStatus(true)
  112. defer c.setStorageLimitExceededMailerJobStatus(false)
  113. lockStatus := c.LockController.TryLock(StorageLimitExceededMailLock, time.MicrosecondsAfterHours(24))
  114. if !lockStatus {
  115. log.Error("Could not acquire lock to send storage limit exceeded mails")
  116. return
  117. }
  118. defer c.LockController.ReleaseLock(StorageLimitExceededMailLock)
  119. users, err := c.UserRepo.GetUsersWithIndividualPlanWhoHaveExceededStorageQuota()
  120. if err != nil {
  121. log.Error("Error while fetching user list", err)
  122. return
  123. }
  124. for _, u := range users {
  125. lastNotificationTime, err := c.NotificationHistoryRepo.GetLastNotificationTime(u.ID, StorageLimitExceededTemplateID)
  126. logger := log.WithFields(log.Fields{
  127. "user_id": u.ID,
  128. })
  129. if err != nil {
  130. logger.Error("Could not fetch last notification time", err)
  131. continue
  132. }
  133. if lastNotificationTime > 0 {
  134. continue
  135. }
  136. logger.Info("Alerting about storage limit exceeded")
  137. err = email.SendTemplatedEmail([]string{u.Email}, "team@ente.io", "team@ente.io", StorageLimitExceededSubject, StorageLimitExceededTemplate, nil, nil)
  138. if err != nil {
  139. logger.Info("Error notifying", err)
  140. continue
  141. }
  142. c.NotificationHistoryRepo.SetLastNotificationTimeToNow(u.ID, StorageLimitExceededTemplateID)
  143. }
  144. }
  145. func (c *EmailNotificationController) setStorageLimitExceededMailerJobStatus(isSending bool) {
  146. c.isSendingStorageLimitExceededMails = isSending
  147. }