From 4b7b712374191966520fc576108de216975b2edc Mon Sep 17 00:00:00 2001 From: Jeremy Butler Date: Fri, 14 Dec 2018 13:53:48 -0700 Subject: [PATCH] Send an email if a bounty is funded below a threshold Fixes: https://github.com/gitcoinco/web/issues/2808 --- app/app/settings.py | 3 +++ app/dashboard/helpers.py | 20 +++++++++++++- app/dashboard/notifications.py | 26 +++++++++++++++++++ app/dashboard/tests/test_dashboard_helpers.py | 7 ++++- app/dashboard/tests/test_notifications.py | 12 ++++++++- 5 files changed, 65 insertions(+), 3 deletions(-) diff --git a/app/app/settings.py b/app/app/settings.py index de188a6de1d..5f514e7848f 100644 --- a/app/app/settings.py +++ b/app/app/settings.py @@ -694,3 +694,6 @@ 'name': 'Index View', }] SILKY_MAX_RECORDED_REQUESTS_CHECK_PERCENT = env.int('SILKY_MAX_RECORDED_REQUESTS_CHECK_PERCENT', default=10) + +# Sending an email when a bounty is funded below a threshold +LOWBALL_BOUNTY_THRESHOLD = env.float('LOWBALL_BOUNTY_THRESHOLD', default=10.00) diff --git a/app/dashboard/helpers.py b/app/dashboard/helpers.py index 64ee1335596..0c7e7c14135 100644 --- a/app/dashboard/helpers.py +++ b/app/dashboard/helpers.py @@ -36,7 +36,7 @@ ) from dashboard.notifications import ( maybe_market_to_email, maybe_market_to_github, maybe_market_to_slack, maybe_market_to_twitter, - maybe_market_to_user_discord, maybe_market_to_user_slack, + maybe_market_to_user_discord, maybe_market_to_user_slack, notify_of_lowball_bounty, ) from dashboard.tokens import addr_to_token from economy.utils import ConversionRateNotFoundError, convert_amount @@ -801,6 +801,19 @@ def record_user_action(event_name, old_bounty, new_bounty): }) +def is_lowball_bounty(bounty_value_usdt): + """Determine if a bounty value is less than a threshold + + Args: + bounty_value_usdt (Decimal): The value of the bounty + + Returns: + bool: True if bounty value is less than the threshold + + """ + return bounty_value_usdt < settings.LOWBALL_BOUNTY_THRESHOLD + + def process_bounty_changes(old_bounty, new_bounty): """Process Bounty changes. @@ -853,6 +866,11 @@ def process_bounty_changes(old_bounty, new_bounty): if new_bounty.fulfillments.exists(): profile_pairs = build_profile_pairs(new_bounty) + # Send an Email if this is a LowBall bounty + if(not old_bounty or old_bounty.value_in_usdt != new_bounty.value_in_usdt): + if is_lowball_bounty(new_bounty.value_in_usdt): + notify_of_lowball_bounty(new_bounty) + # marketing if event_name != 'unknown_event': print("============ posting ==============") diff --git a/app/dashboard/notifications.py b/app/dashboard/notifications.py index ebef4a141f9..056a34a7551 100644 --- a/app/dashboard/notifications.py +++ b/app/dashboard/notifications.py @@ -27,6 +27,7 @@ from django.templatetags.static import static from django.utils import timezone, translation from django.utils.translation import gettext +from django.utils.translation import gettext_lazy as _ import requests import twitter @@ -42,6 +43,31 @@ logger = logging.getLogger(__name__) +def notify_of_lowball_bounty(bounty): + """Send an email to founders@gitcoin.co with the lowball bounty info + + Args: + bounty (dashboard.models.Bounty): The lowball bounty object + + """ + to_email = 'founders@gitcoin.co' + from_email = settings.CONTACT_EMAIL + cur_language = translation.get_language() + try: + setup_lang(to_email) + subject = _("Low Bounty Notification") + body = \ + f"Bounty: {bounty}\n\n" \ + f"url: {bounty.url}\n\n" \ + f"Owner Name: {bounty.bounty_owner_name}\n\n" \ + f"Owner Email: {bounty.bounty_owner_email}\n\n" \ + f"Owner Address: {bounty.bounty_owner_address}\n\n" \ + f"Owner Profile: {bounty.bounty_owner_profile}" + send_mail(from_email, to_email, subject, body, from_name=_("No Reply from Gitcoin.co"), categories=['admin'], ) + finally: + translation.activate(cur_language) + + def github_org_to_twitter_tags(github_org): """Build a string of github organization twitter tags. diff --git a/app/dashboard/tests/test_dashboard_helpers.py b/app/dashboard/tests/test_dashboard_helpers.py index 0ad77e1ee40..305546cb03b 100644 --- a/app/dashboard/tests/test_dashboard_helpers.py +++ b/app/dashboard/tests/test_dashboard_helpers.py @@ -21,11 +21,12 @@ from datetime import date, datetime, timedelta from unittest.mock import patch +from django.conf import settings from django.test.client import RequestFactory import pytz import requests_mock -from dashboard.helpers import amount, issue_details, normalize_url, process_bounty_details +from dashboard.helpers import amount, is_lowball_bounty, issue_details, normalize_url, process_bounty_details from dashboard.models import Bounty from economy.models import ConversionRate from marketing.mails import featured_funded_bounty @@ -52,6 +53,10 @@ def test_amount(self): request = self.factory.get('/sync/get_amount', params) assert amount(request).content == b'{"eth": 5.0, "usdt": 10.0}' + def test_lowball_bounty(self): + assert is_lowball_bounty(settings.LOWBALL_BOUNTY_THRESHOLD - 1.0) + assert not is_lowball_bounty(settings.LOWBALL_BOUNTY_THRESHOLD) + def test_normalize_url(self): """Test the dashboard helper normalize_url method.""" assert normalize_url('https://gitcoin.co/') == 'https://gitcoin.co' diff --git a/app/dashboard/tests/test_notifications.py b/app/dashboard/tests/test_notifications.py index a001841a4a3..ccf7f6366b4 100644 --- a/app/dashboard/tests/test_notifications.py +++ b/app/dashboard/tests/test_notifications.py @@ -18,9 +18,12 @@ """ from datetime import datetime +from unittest.mock import patch from dashboard.models import Bounty -from dashboard.notifications import amount_usdt_open_work, append_snooze_copy, build_github_notification +from dashboard.notifications import ( + amount_usdt_open_work, append_snooze_copy, build_github_notification, notify_of_lowball_bounty, +) from pytz import UTC from test_plus.test import TestCase @@ -38,7 +41,9 @@ def setUp(self): github_url='https://github.com/gitcoinco/web/issues/11', token_address='0x0', issue_description='hello world', + bounty_owner_name="Fred", bounty_owner_github_username='flintstone', + bounty_owner_email="fred.flintstone@bedrock.com" is_open=False, accepted=True, expires_date=datetime(2008, 11, 30, tzinfo=UTC), @@ -87,6 +92,11 @@ def test_append_snooze_copy(self): copy = f'\nFunders only: Snooze warnings for {copy}' assert segments[i] == copy + @patch('marketing.mails.send_mail') + def test_notify_of_lowball_bounty(self): + notify_of_lowball_bounty(self.bounty) + assert mock_send_mail.call_count == 1 + def tearDown(self): """Perform cleanup for the testcase.""" self.bounty.delete()