diff --git a/app/dashboard/helpers.py b/app/dashboard/helpers.py index db4ca1fd523..1ba426e1618 100644 --- a/app/dashboard/helpers.py +++ b/app/dashboard/helpers.py @@ -33,7 +33,7 @@ from dashboard.models import Activity, Bounty, BountyFulfillment, BountySyncRequest, UserAction 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 convert_amount @@ -670,6 +670,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 < 10.00 + + def process_bounty_changes(old_bounty, new_bounty): """Process Bounty changes. @@ -721,6 +734,10 @@ 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 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 f2b46e50b67..590d6a49204 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 b71a5653ce8..3d94f86f623 100644 --- a/app/dashboard/tests/test_dashboard_helpers.py +++ b/app/dashboard/tests/test_dashboard_helpers.py @@ -22,7 +22,7 @@ from django.test.client import RequestFactory import requests_mock -from dashboard.helpers import amount, issue_details, normalize_url +from dashboard.helpers import amount, is_lowball_bounty, issue_details, normalize_url from economy.models import ConversionRate from test_plus.test import TestCase @@ -33,7 +33,7 @@ class DashboardHelpersTest(TestCase): def setUp(self): """Perform setup for the testcase.""" self.factory = RequestFactory() - ConversionRate.objects.create( + ConversionRate.objects.create( from_amount=1, to_amount=2, source='etherdelta', @@ -47,6 +47,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(1.00) == True + assert is_lowball_bounty(15.00) == False + 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()