Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send an email if a bounty is funded below a threshold #3219

Merged
merged 5 commits into from
Nov 6, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -696,3 +696,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)
20 changes: 19 additions & 1 deletion app/dashboard/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -805,6 +805,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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will result in a TypeError if value_usdt is None



def process_bounty_changes(old_bounty, new_bounty):
"""Process Bounty changes.

Expand Down Expand Up @@ -857,6 +870,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):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have just a question about this, what happens if is a token and for some reason we don't have the usd value? It will affect the rest of the flow or just fail silently?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@octavioamu thats a really good point - @oddballbutler can you please add a test case to cover this?

notify_of_lowball_bounty(new_bounty)

# marketing
if event_name != 'unknown_event':
print("============ posting ==============")
Expand Down
26 changes: 26 additions & 0 deletions app/dashboard/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -42,6 +43,31 @@
logger = logging.getLogger(__name__)


def notify_of_lowball_bounty(bounty):
"""Send an email to [email protected] with the lowball bounty info
Args:
bounty (dashboard.models.Bounty): The lowball bounty object
"""
to_email = '[email protected]'
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" \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having the amount in here would sure be nice :)
also it should probably only happen if bounty is on mainnet

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.
Expand Down
7 changes: 6 additions & 1 deletion app/dashboard/tests/test_dashboard_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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'