Skip to content

Commit

Permalink
New Email for Tribe Members about Hackathon Prizes (#7146)
Browse files Browse the repository at this point in the history
* setup web preview url

* implement render_tribe_hackathon_prizes

* add new email_header_hackathon.png banner image

* build template for tribe_hackathon_prizes_email

* management command for tribe_hackathon_prizes

* setup cron job

* email intro util function

* rewrite tribe_hackathon_prizes()

* rewrite render_tribe_hackathon_prizes()

* rewrite web preview function

* rewrite template()
  • Loading branch information
sebastiantf authored Sep 30, 2020
1 parent 39aa579 commit 0632270
Show file tree
Hide file tree
Showing 12 changed files with 269 additions and 2 deletions.
1 change: 1 addition & 0 deletions app/app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@
path('_administration/email/gdpr_reconsent', retail.emails.gdpr_reconsent, name='gdpr_reconsent'),
path('_administration/email/share_bounty', retail.emails.share_bounty, name='share_bounty'),
path('_administration/email/new_tip/resend', retail.emails.resend_new_tip, name='resend_new_tip'),
path('_administration/email/tribe_hackathon_prizes', retail.emails.tribe_hackathon_prizes, name='tribe_hackathon_prizes'),
path(
'_administration/email/day_email_campaign/<int:day>',
marketing.views.day_email_campaign,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions app/marketing/mails.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@
render_successful_contribution_email, render_support_cancellation_email, render_tax_report,
render_thank_you_for_supporting_email, render_tip_email, render_unread_notification_email_weekly_roundup,
render_wallpost, render_weekly_recap,
render_bounty_expire_warning, render_bounty_feedback, render_bounty_request, render_bounty_startwork_expire_warning,
render_bounty_unintersted, render_comment, render_faucet_rejected, render_faucet_request,
render_featured_funded_bounty, render_funder_payout_reminder, render_funder_stale, render_gdpr_reconsent,
render_gdpr_update, render_grant_cancellation_email, render_grant_recontribute, render_grant_txn_failed,
render_grant_update, render_kudos_email, render_match_distribution, render_match_email, render_mention,
render_new_bounty, render_new_bounty_acceptance, render_new_bounty_rejection, render_new_bounty_roundup,
render_new_grant_email, render_new_supporter_email, render_new_work_submission, render_no_applicant_reminder,
render_nth_day_email_campaign, render_quarterly_stats, render_remember_your_cart, render_request_amount_email,
render_reserved_issue, render_share_bounty, render_start_work_applicant_about_to_expire,
render_start_work_applicant_expired, render_start_work_approved, render_start_work_new_applicant,
render_start_work_rejected, render_subscription_terminated_email, render_successful_contribution_email,
render_support_cancellation_email, render_tax_report, render_thank_you_for_supporting_email, render_tip_email,
render_unread_notification_email_weekly_roundup, render_wallpost, render_weekly_recap, render_bounty_hypercharged,
render_tribe_hackathon_prizes, render_unread_notification_email_weekly_roundup, render_wallpost, render_weekly_recap,
)
from sendgrid.helpers.mail import Attachment, Content, Email, Mail, Personalization
from sendgrid.helpers.stats import Category
Expand Down Expand Up @@ -1997,3 +2011,47 @@ def remember_your_cart(profile, cart_query, grants, hours):
send_mail(from_email, to_email, subject, text, html, categories=['marketing', func_name()])
finally:
translation.activate(cur_language)

def tribe_hackathon_prizes(hackathon):
from dashboard.models import TribeMember, Sponsor
from marketing.utils import generate_hackathon_email_intro

sponsors = hackathon.sponsors.all()
tribe_members_in_sponsors = TribeMember.objects.filter(org__in=[sponsor.tribe for sponsor in sponsors]).exclude(status='rejected').exclude(profile__user=None).only('profile')

for tribe_member in tribe_members_in_sponsors.distinct('profile'):
tribe_member_records = tribe_members_in_sponsors.filter(profile=tribe_member.profile)

sponsors_prizes = []
for sponsor in sponsors.filter(tribe__in=[tribe_member_record.org for tribe_member_record in tribe_member_records]):
prizes = hackathon.get_current_bounties.filter(bounty_owner_profile=sponsor.tribe)
sponsor_prize = {
"sponsor": sponsor,
"prizes": prizes
}
sponsors_prizes.append(sponsor_prize)

subject_begin = generate_hackathon_email_intro(sponsors_prizes)
subject = f"{subject_begin} participating in {hackathon.name} on Gitcoin 🚀"

try:
html, text = render_tribe_hackathon_prizes(hackathon, sponsors_prizes, subject_begin)
except:
return

profile = tribe_member.profile
to_email = profile.email
from_email = settings.CONTACT_EMAIL
if not to_email:
if profile and profile.user:
to_email = profile.user.email
if not to_email:
continue

cur_language = translation.get_language()

try:
setup_lang(to_email)
send_mail(from_email, to_email, subject, text, html, categories=['marketing', func_name()])
finally:
translation.activate(cur_language)
41 changes: 41 additions & 0 deletions app/marketing/management/commands/tribe_hackathon_prizes_email.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'''
Copyright (C) 2020 Gitcoin Core
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''
import datetime

from django.conf import settings
from django.core.management.base import BaseCommand
from django.utils import timezone

from dashboard.models import HackathonEvent
from marketing.mails import tribe_hackathon_prizes


class Command(BaseCommand):
help = 'sends emails for tribe members about hackathon prizes sponsored by the tribe org'

def handle(self, *args, **options):
if settings.DEBUG:
print("not active in non prod environments")
return

no_of_days = 3
next_date = timezone.now() + timezone.timedelta(days=no_of_days)

upcoming_hackthons = HackathonEvent.objects.filter(start_date__date=next_date)

for upcoming_hackthon in upcoming_hackthons:
try:
tribe_hackathon_prizes(upcoming_hackthon)
except:
pass
8 changes: 8 additions & 0 deletions app/marketing/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,14 @@ def handle_marketing_callback(_input, request):
else:
messages.info(request, "You have been selected to receive a $5.00 Gitcoin Grants voucher. Login to use it.")

def generate_hackathon_email_intro(sponsors_prizes):
sponsor_names = [sponsor['sponsor'].name for sponsor in sponsors_prizes]
if (len(sponsors_prizes) > 2):
return f"{', '.join(sponsor_names)} are"
elif (len(sponsors_prizes) == 2):
return f"{' and '.join(sponsor_names)} are"
else:
return f"{sponsors_prizes[0]['sponsor'].name} is"

def func_name():
"""Determine the calling function's name.
Expand Down
47 changes: 47 additions & 0 deletions app/retail/emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,34 @@ def render_tip_email(to_email, tip, is_new):

return response_html, response_txt

def render_tribe_hackathon_prizes(hackathon, sponsors_prizes, intro_begin):
email_style = 'hackathon'

hackathon = {
'hackathon': hackathon,
'name': hackathon.name,
'image_url': hackathon.logo.url if hackathon.logo else f'{settings.STATIC_URL}v2/images/emails/hackathons-neg.png',
'url': hackathon.url,
}

for sponsor_prize in sponsors_prizes:
sponsor_prize['name'] = sponsor_prize['sponsor'].name
sponsor_prize['image_url'] = sponsor_prize['sponsor'].logo.url if sponsor_prize['sponsor'].logo else f'{settings.STATIC_URL}v2/images/emails/hackathons-neg.png'

intro = f"{intro_begin} participating on a new hackathon on Gitcoin: "

params = {
'hackathon': hackathon,
'sponsors_prizes': sponsors_prizes,
'intro': intro,
'email_style': email_style,
'hide_bottom_logo': True,
}

response_html = premailer_transform(render_to_string("emails/tribe_hackathon_prizes.html", params))
response_txt = render_to_string("emails/tribe_hackathon_prizes.txt", params)

return response_html, response_txt

def render_request_amount_email(to_email, request, is_new):

Expand Down Expand Up @@ -1660,7 +1688,26 @@ def start_work_applicant_expired(request):
response_html, _, _ = render_start_work_applicant_expired(interest, bounty)
return HttpResponse(response_html)

@staff_member_required
def tribe_hackathon_prizes(request):
from dashboard.models import HackathonEvent
from marketing.utils import generate_hackathon_email_intro

hackathon = HackathonEvent.objects.filter(start_date__date=(timezone.now()+timezone.timedelta(days=3))).first()

sponsors_prizes = []
for sponsor in hackathon.sponsors.all()[:3]:
prizes = hackathon.get_current_bounties.filter(bounty_owner_profile=sponsor.tribe)
sponsor_prize = {
"sponsor": sponsor,
"prizes": prizes
}
sponsors_prizes.append(sponsor_prize)

intro_begin = generate_hackathon_email_intro(sponsors_prizes)

response_html, _ = render_tribe_hackathon_prizes(hackathon,sponsors_prizes, intro_begin)
return HttpResponse(response_html)

def render_remember_your_cart(grants_query, grants, hours):
params = {
Expand Down
8 changes: 6 additions & 2 deletions app/retail/templates/emails/bounty.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,14 @@
<li style="list-style:none; margin-left: 0;">
{% if bounty.avatar_url %}
<img style="border-radius: 20px; display: block; margin-left: auto; margin-right: auto; margin-bottom: 0.5em" src="{{ bounty.avatar_url }}" width=50px height=50px>
<a style="font-weight: bold; text-decoration: none;" href="{% url "profile" highlight.who %}">{{ bounty.org_name }}</a>
{% if not prize %}
<a style="font-weight: bold; text-decoration: none;" href="{% url "profile" highlight.who %}">{{ bounty.org_name }}</a>
{% endif %}
{% else %}
* <strong>{{ bounty.org_name }}</strong>
{% endif %}
<p style="margin-bottom: 10px; margin-top:0">
{% if prize %}<b>{% endif %}
{% if primer %}
{{ primer }}
{% elif bounty.title %}
Expand All @@ -70,6 +73,7 @@
{% endif %}
{{ bounty.title }}
{% endif %}
{% if prize %}</b>{% endif %}
</p>
</li>
</ul>
Expand Down Expand Up @@ -137,5 +141,5 @@
</p>
{% endif %}
{% endif %}
{% include 'emails/shared_bounty_actions.html' %}
{% include 'emails/shared_bounty_actions.html' with prize=prize %}
</div>
4 changes: 4 additions & 0 deletions app/retail/templates/emails/shared_bounty_actions.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
<div style="margin-bottom: 2em; margin-top: 2em;">
<a class="button" href="{{ action_url }}">{{ action_copy }}</a>
</div>
{% elif prize %}
<div style="margin-bottom: 1em; margin-top: 1em;">
<a class="button large" href="{{ bounty.absolute_url }}">{% trans "View Prize" %}</a>
</div>
{% else %}
<div style="margin-bottom: 1em; margin-top: 1em;">
<a class="button" href="{{ bounty.absolute_url }}">{% trans "View on Gitcoin.co" %}</a>
Expand Down
1 change: 1 addition & 0 deletions app/retail/templates/emails/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,7 @@
{% elif email_style == 26 %} <img id="logo" src="{% static "v2/images/emails/email_header26.png" %}" alt="Gitcoin" title="Gitcoin Logo">
{% elif email_style == 27 %} <img id="logo" src="{% static "v2/images/emails/email_header27.png" %}" alt="Gitcoin" title="Gitcoin Logo">
{% elif email_style == 28 %} <img id="logo" src="{% static "v2/images/emails/email_header28.png" %}" alt="Gitcoin" title="Gitcoin Logo">
{% elif email_style == 'hackathon' %} <img id="logo" src="{% static "v2/images/emails/email_header_hackathon.png" %}" alt="Gitcoin" title="Gitcoin Logo">
{% else %}
<img id="logo" src="{% static "v2/images/logo_large.png" %}" alt="Gitcoin" title="Gitcoin Logo">
{% endif %}
Expand Down
88 changes: 88 additions & 0 deletions app/retail/templates/emails/tribe_hackathon_prizes.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
{% extends 'emails/template.html' %}
{% comment %}
Copyright (C) 2018 Gitcoin Core

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
{% endcomment %}
{% load i18n humanize %}

{% block content %}

<style>
.sponsor-logo {
width: 65px;
height: 65px;
margin: 20px 0;
}
.hackathon-image {
width: 100%;
height: 200px;
margin-top: 30px;
background-color: #000000;
}
.left {
text-align: left;
}
.message {
margin-top: 3em;
margin-bottom: 0;
}
.container p a {
color: #3E00FF;
}
.inner-container {
width: 75%;
margin-left: auto;
margin-right: auto;
}
</style>

<div class="container" style="margin-bottom: 3em; padding: 0;">
<div class="inner-container">
{% for sponsor in sponsors_prizes %}
<img class="sponsor-logo" src="{{sponsor.image_url}}">
{% endfor %}
<h1>Win exciting prizes at {{ hackathon.name }}</h1>

<p class="left message"><b>{{intro}}<b>{{ hackathon.name }}</b> 🚀</p>

{% if hackathon %}
{% if hackathon.image_url %}
<img class="hackathon-image" src="{{hackathon.image_url}}">
{% endif %}
<div style="margin-bottom: 2em; margin-top: 2em;">
<a class="button large" href="{{ hackathon.url }}">Join Hackathon</a>
</div>
{% endif %}

<p class="left message">Meet a community of like-minded hackers, buidl cool stuff, and win these exciting prizes:</p>
<div style="margin-bottom: 3em;">
{% for sponsor in sponsors_prizes %}
{% if sponsor.prizes %}
<div style="margin: 4em 0">
<h3 style="text-decoration: underline;">Bounties by {{sponsor.name}}:</h3>
{% for prize in sponsor.prizes %}
{% include 'emails/bounty.html' with bounty=prize count=forloop.counter small=1 prize=1 %}
{% endfor %}
{% endif %}
</div>
{% endfor %}
</div>

<p class="left" style="margin-top: 5em;">See you @ <a href="{{ hackathon.url }}">{{ hackathon.name }}</a>!</p>

<p class="left">The Gitcoin team</p>
</div>
</div>
{% endblock %}
14 changes: 14 additions & 0 deletions app/retail/templates/emails/tribe_hackathon_prizes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Win exciting prizes with <br> {{ sponsor.name }}

{{ sponsor.name }} is participating on a new hackathon on Gitcoin: {{ hackathon.name }} 🚀

{% if prizes %}
Meet a community of like-minded hackers, buidl cool stuff, and win these exciting prizes:
{% for prize in prizes %}
{% include 'emails/bounty.html' with bounty=prize count=forloop.counter small=1 prize=1 %}
{% endfor %}
{% endif %}

See you @ {{ hackathon.name }}!

The Gitcoin team
1 change: 1 addition & 0 deletions scripts/crontab
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/us
15 10 * * * cd gitcoin/coin; bash scripts/run_management_command_if_not_already_running.bash bounty_feedback_email >> /var/log/gitcoin/bounty_feedback_email.log 2>&1
15 10 * * * cd gitcoin/coin; bash scripts/run_management_command_if_not_already_running.bash funder_stale_email 60 >> /var/log/gitcoin/funder_stale_email.log 2>&1
15 5 * * * cd gitcoin/coin; bash scripts/run_management_command_if_not_already_running.bash new_bounties_email >> /var/log/gitcoin/new_bounties_email.log 2>&1
15 10 * * * cd gitcoin/coin; bash scripts/run_management_command_if_not_already_running.bash tribe_hackathon_prizes_email >> /var/log/gitcoin/tribe_hackathon_prizes_email.log 2>&1
30 6 * * * cd gitcoin/coin; bash scripts/run_management_command_if_not_already_running.bash post_data grants >> /var/log/gitcoin/post_data.log 2>&1
15 15 * * * cd gitcoin/coin; bash scripts/run_management_command_if_not_already_running.bash post_data quote >> /var/log/gitcoin/post_data.log 2>&1
15 18 * * * cd gitcoin/coin; bash scripts/run_management_command_if_not_already_running.bash post_data results >> /var/log/gitcoin/post_data.log 2>&1
Expand Down

0 comments on commit 0632270

Please sign in to comment.