def async_create_or_update_achievement(user_achievement: UserAchievement): user = user_achievement.user achievement = user_achievement.achievement # messages if user.is_club_member and user.telegram_id: if achievement.image: send_telegram_image( chat=Chat(id=user.telegram_id), image_url=achievement.image, text=render_html_message("achievement.html", user=user, achievement=achievement), ) # emails if not user.is_email_unsubscribed: email_template = loader.get_template("emails/achievement.html") send_club_email(recipient=user.email, subject=f"🏆 Вы получили ачивку «{achievement.name}»", html=email_template.render({ "user": user, "achievement": achievement }), tags=["achievement"])
def send_delete_account_request_email(user: User, code: Code): auth_template = loader.get_template("emails/delete_account_request.html") send_club_email( recipient=user.email, subject=f"🧨 Код для удаления аккаунта", html=auth_template.render({"user": user, "code": code}), tags=["killme"] )
def send_data_archive_ready_email(user: User, url: str): auth_template = loader.get_template("emails/data_archive_ready.html") send_club_email( recipient=user.email, subject=f"💽 Ваш архив с данными готов", html=auth_template.render({"user": user, "url": url}), tags=["gdpr"] )
def send_ping_email(user: User, message: str): ping_template = loader.get_template("emails/ping.html") send_club_email( recipient=user.email, subject=f"👋 Вам письмо", html=ping_template.render({"message": message}), tags=["ping"] )
def send_delete_account_confirm_email(user: User): auth_template = loader.get_template("emails/delete_account_confirm.html") send_club_email( recipient=user.email, subject=f"✌️ Ваш аккаунт в Клубе будет удалён", html=auth_template.render({"user": user}), tags=["killme"] )
def send_unmoderated_email(user: User): rejected_template = loader.get_template("emails/unmoderated.html") send_club_email( recipient=user.email, subject=f"😱 Вас размодерировали", html=rejected_template.render({"user": user}), tags=["unmoderated"] )
def send_registration_email(user: User): registration_template = loader.get_template("emails/registration.html") send_club_email( recipient=user.email, subject=f"Ваше приглашение 🪪", html=registration_template.render({"user": user}), tags=["registration"] )
def send_welcome_drink(user: User): welcome_drink_template = loader.get_template("emails/welcome.html") send_club_email( recipient=user.email, subject=f"Велком дринк 🍸", html=welcome_drink_template.render({"user": user}), tags=["welcome"] )
def send_auth_email(user: User, code: Code): auth_template = loader.get_template("emails/auth.html") send_club_email( recipient=user.email, subject=f"{code.code} — ваш код для входа", html=auth_template.render({"user": user, "code": code}), tags=["auth"] )
def send_renewal_email(user: User): renewal_template = loader.get_template("emails/renewal.html") send_club_email( recipient=user.email, subject=f"Ваша подписка стала еще длинее!", html=renewal_template.render({"user": user}), tags=["renewal"] )
def send_invite_confirmation(from_user: User, to_user: User): invite_template = loader.get_template("emails/invite_confirm.html") send_club_email(recipient=from_user.email, subject=f"👍 Вы пригласили '{to_user.email}' в Клуб", html=invite_template.render({ "from_user": from_user, "to_user": to_user }), tags=["invited"])
def send_invited_email(from_user: User, to_user: User): invite_template = loader.get_template("emails/invited.html") send_club_email(recipient=to_user.email, subject=f"🚀 Вас пригласили в Клуб", html=invite_template.render({ "from_user": from_user, "to_user": to_user }), tags=["invited"])
def send_rejected_email(user: User, reason: RejectReason): try: rejected_template = loader.get_template( f"emails/rejected/{reason.value}.html") except TemplateDoesNotExist: rejected_template = loader.get_template(f"emails/rejected/intro.html") send_club_email(recipient=user.email, subject=f"😕 Пока нет", html=rejected_template.render({"user": user}), tags=["rejected"])
def send_banned_email(user: User, days: int, reason: str): if not user.is_banned or not days: return # not banned oO rejected_template = loader.get_template("emails/banned.html") send_club_email(recipient=user.email, subject=f"💩 Вас забанили", html=rejected_template.render({ "user": user, "days": days, "reason": reason, }), tags=["banned"])
def handle(self, *args, **options): # select daily subscribers subscribed_users = User.objects\ .filter( email_digest_type=User.EMAIL_DIGEST_TYPE_DAILY, is_email_verified=True, membership_expires_at__gte=datetime.utcnow() - timedelta(days=14), moderation_status=User.MODERATION_STATUS_APPROVED )\ .exclude(is_email_unsubscribed=True) for user in subscribed_users: if not options.get("production") and user.email != "*****@*****.**": self.stdout.write( "Test mode. Use --production to send the digest to all users" ) continue # render user digest using a special html endpoint digest_url = "https://vas3k.club" + reverse( "render_daily_digest", kwargs={"user_slug": user.slug}) self.stdout.write(f"Generating digest for user: {user.slug}") digest_html_response = requests.get(digest_url) if digest_html_response.status_code > 400: log.error("Empty digest. Skipping") continue user_digest_html = digest_html_response.text user_digest_html = user_digest_html\ .replace("%username%", user.slug)\ .replace("%user_id%", str(user.id))\ .replace("%secret_code%", user.secret_hash) self.stdout.write(f"Sending email to {user.email}...") try: send_club_email( recipient=user.email, subject= f"лћл░л╣л┤лХлхЛЂЛѓ лил░ {date(datetime.utcnow(), 'd E')}", html=user_digest_html, tags=["daily_digest"]) except Exception as ex: self.stdout.write(f"Sending to {user.email} failed: {ex}") continue self.stdout.write("Done ЪЦЎ")
def handle(self, *args, **options): # select daily subscribers subscribed_users = User.objects\ .filter( email_digest_type=User.EMAIL_DIGEST_TYPE_DAILY, is_email_verified=True, membership_expires_at__gte=datetime.utcnow() - timedelta(days=14), moderation_status=User.MODERATION_STATUS_APPROVED, )\ .exclude(is_email_unsubscribed=True) for user in subscribed_users: if not options.get("production") and user.email not in dict(settings.ADMINS).values(): self.stdout.write("Test mode. Use --production to send the digest to all users") continue # render user digest using a special html endpoint self.stdout.write(f"Generating digest for user: {user.slug}") try: digest = generate_daily_digest(user) except NotFound: self.stdout.write("Empty digest. Skipping") continue digest = digest\ .replace("%username%", user.slug)\ .replace("%user_id%", str(user.id))\ .replace("%secret_code%", base64.b64encode(user.secret_hash.encode("utf-8")).decode()) self.stdout.write(f"Sending email to {user.email}...") try: send_club_email( recipient=user.email, subject=f"лћл░л╣л┤лХлхЛЂЛѓ лил░ {date(datetime.utcnow(), 'd E')}", html=digest, tags=["daily_digest"] ) except Exception as ex: self.stdout.write(f"Sending to {user.email} failed: {ex}") continue self.stdout.write("Done ЪЦЎ")
def async_create_or_update_badge(user_badge: UserBadge): to_user = user_badge.to_user # messages if to_user.is_member and to_user.telegram_id: send_telegram_image( chat=Chat(id=to_user.telegram_id), image_url= f"{settings.APP_HOST}/static/images/badges/big/{user_badge.badge.code}.png", text=render_html_message("badge.html", user_badge=user_badge), ) # emails if not to_user.is_email_unsubscribed: email_template = loader.get_template("emails/badge.html") send_club_email( recipient=to_user.email, subject=f"🏅 Вам подарили награду «{user_badge.badge.title}»", html=email_template.render({"user_badge": user_badge}), tags=["badge"])
def handle(self, *args, **options): # render digest using a special html endpoint digest_url = "https://vas3k.club" + reverse("render_weekly_digest") self.stdout.write(f"Generating digest: {digest_url}") digest_html_response = requests.get(digest_url) if digest_html_response.status_code > 400: log.error("Weekly digest error: bad status code", extra={"html": digest_html_response.text}) return digest_html = digest_html_response.text # save digest as a post issue = (datetime.utcnow() - settings.LAUNCH_DATE).days // 7 year, week, _ = (datetime.utcnow() - timedelta(days=7)).isocalendar() post, _ = Post.objects.update_or_create( slug=f"{year}_{week}", type=Post.TYPE_WEEKLY_DIGEST, defaults=dict( author=User.objects.filter(slug="vas3k").first(), title=f"Клубный журнал. Итоги недели. Выпуск #{issue}", html=digest_html, text=digest_html, is_pinned_until=datetime.utcnow() + timedelta(days=1), is_visible=True, is_public=False, ) ) SearchIndex.update_post_index(post) # sending emails subscribed_users = User.objects\ .filter( is_email_verified=True, membership_expires_at__gte=datetime.utcnow() - timedelta(days=14) )\ .exclude(email_digest_type=User.EMAIL_DIGEST_TYPE_NOPE)\ .exclude(is_profile_rejected=True)\ .exclude(is_email_unsubscribed=True) for user in subscribed_users: self.stdout.write(f"Sending to {user.email}...") if not options.get("production") and user.email != "*****@*****.**": self.stdout.write("Test mode. Use --production to send the digest to all users") continue try: user_digest_html = str(digest_html) user_digest_html = user_digest_html\ .replace("%username%", user.slug)\ .replace("%user_id%", str(user.id))\ .replace("%secret_code%", user.secret_hash) send_club_email( recipient=user.email, subject=f"🤘 Клубный журнал. Итоги недели. Выпуск #{issue}", html=user_digest_html, tags=["weekly_digest", f"weekly_digest_{issue}"] ) except Exception as ex: self.stdout.write(f"Sending to {user.email} failed: {ex}") log.exception(f"Error while sending an email to {user.email}") continue if options.get("production"): # flush digest intro for next time GodSettings.objects.update(digest_intro=None) send_telegram_message( chat=CLUB_CHANNEL, text=render_html_message("weekly_digest_announce.html", post=post), disable_preview=False, parse_mode=telegram.ParseMode.HTML, ) self.stdout.write("Done 🥙")
def send_rejected_email(user): rejected_template = loader.get_template("emails/rejected.html") send_club_email(recipient=user.email, subject=f"😕 Пока нет", html=rejected_template.render({"user": user}), tags=["rejected"])
def handle(self, *args, **options): # render digest using a special html endpoint try: digest = generate_weekly_digest() except NotFound: log.error("Weekly digest is empty") return # get a version without "unsubscribe" footer for posting on home page digest_without_footer = generate_weekly_digest(no_footer=True) # save digest as a post issue = (datetime.utcnow() - settings.LAUNCH_DATE).days // 7 year, week, _ = (datetime.utcnow() - timedelta(days=7)).isocalendar() post, _ = Post.objects.update_or_create( slug=f"{year}_{week}", type=Post.TYPE_WEEKLY_DIGEST, defaults=dict( author=User.objects.filter(slug="vas3k").first(), title=f"Клубный журнал. Итоги недели. Выпуск #{issue}", html=digest_without_footer, text=digest_without_footer, is_pinned_until=datetime.utcnow() + timedelta(days=1), is_visible=True, is_public=False, )) # make it searchable SearchIndex.update_post_index(post) # sending emails subscribed_users = User.objects\ .filter( is_email_verified=True, membership_expires_at__gte=datetime.utcnow() - timedelta(days=14), moderation_status=User.MODERATION_STATUS_APPROVED, )\ .exclude(email_digest_type=User.EMAIL_DIGEST_TYPE_NOPE)\ .exclude(is_email_unsubscribed=True) for user in subscribed_users: self.stdout.write(f"Sending to {user.email}...") if not options.get("production") and user.email not in dict( settings.ADMINS).values(): self.stdout.write( "Test mode. Use --production to send the digest to all users" ) continue try: digest = digest\ .replace("%username%", user.slug)\ .replace("%user_id%", str(user.id))\ .replace("%secret_code%", base64.b64encode(user.secret_hash.encode("utf-8")).decode()) send_club_email( recipient=user.email, subject=f"🤘 Клубный журнал. Итоги недели. Выпуск #{issue}", html=digest, tags=["weekly_digest", f"weekly_digest_{issue}"]) except Exception as ex: self.stdout.write(f"Sending to {user.email} failed: {ex}") log.exception(f"Error while sending an email to {user.email}") continue if options.get("production"): # flush digest intro and title for next time GodSettings.objects.update(digest_intro=None, digest_title=None) send_telegram_message( chat=CLUB_CHANNEL, text=render_html_message("weekly_digest_announce.html", post=post), disable_preview=False, parse_mode=telegram.ParseMode.HTML, ) self.stdout.write("Done 🥙")