def uninterested(request, bounty_id, profile_id): """Remove party from given bounty Can only be called by the bounty funder :request method: GET Args: bounty_id (int): ID of the Bounty profile_id (int): ID of the interested profile Returns: dict: The success key with a boolean value and accompanying error. """ try: bounty = Bounty.objects.get(pk=bounty_id) except Bounty.DoesNotExist: return JsonResponse({'errors': ['Bounty doesn\'t exist!']}, status=401) is_funder = bounty.is_funder(request.user.username.lower()) is_staff = request.user.is_staff if not is_funder and not is_staff: return JsonResponse( {'error': 'Only bounty funders are allowed to remove users!'}, status=401) try: interest = Interest.objects.get(profile_id=profile_id, bounty=bounty) bounty.interested.remove(interest) maybe_market_to_slack(bounty, 'stop_work') maybe_market_to_user_slack(bounty, 'stop_work') event_name = "bounty_removed_by_staff" if is_staff else "bounty_removed_by_funder" record_user_action_on_interest(interest, event_name, None) interest.delete() except Interest.DoesNotExist: return JsonResponse( { 'errors': ['Party haven\'t expressed interest on this bounty.'], 'success': False }, status=401) except Interest.MultipleObjectsReturned: interest_ids = bounty.interested \ .filter( profile_id=profile_id, bounty=bounty ).values_list('id', flat=True) \ .order_by('-created') bounty.interested.remove(*interest_ids) Interest.objects.filter(pk__in=list(interest_ids)).delete() profile = Profile.objects.get(id=profile_id) if profile.user and profile.user.email: bounty_uninterested(profile.user.email, bounty, interest) else: print("no email sent -- user was not found") return JsonResponse({'success': True})
def create_new_interest_helper(bounty, user): profile_id = user.profile.pk interest = Interest.objects.create(profile_id=profile_id) bounty.interested.add(interest) record_user_action(user, 'start_work', interest) maybe_market_to_slack(bounty, 'start_work') maybe_market_to_twitter(bounty, 'start_work') return interest
def remove_interest(request, bounty_id): """Unclaim work from the Bounty. Can only be called by someone who has started work :request method: POST post_id (int): ID of the Bounty. Returns: dict: The success key with a boolean value and accompanying error. """ profile_id = request.user.profile.pk if request.user.is_authenticated and hasattr(request.user, 'profile') else None access_token = request.GET.get('token') if access_token: helper_handle_access_token(request, access_token) github_user_data = get_github_user_data(access_token) profile = Profile.objects.filter(handle=github_user_data['login']).first() profile_id = profile.pk if not profile_id: return JsonResponse( {'error': _('You must be authenticated via github to use this feature!')}, status=401) try: bounty = Bounty.objects.get(pk=bounty_id) except Bounty.DoesNotExist: return JsonResponse({'errors': ['Bounty doesn\'t exist!']}, status=401) try: interest = Interest.objects.get(profile_id=profile_id, bounty=bounty) record_user_action(request.user, 'stop_work', interest) bounty.interested.remove(interest) interest.delete() maybe_market_to_slack(bounty, 'stop_work') maybe_market_to_user_slack(bounty, 'stop_work') maybe_market_to_twitter(bounty, 'stop_work') except Interest.DoesNotExist: return JsonResponse({ 'errors': [_('You haven\'t expressed interest on this bounty.')], 'success': False}, status=401) except Interest.MultipleObjectsReturned: interest_ids = bounty.interested \ .filter( profile_id=profile_id, bounty=bounty ).values_list('id', flat=True) \ .order_by('-created') bounty.interested.remove(*interest_ids) Interest.objects.filter(pk__in=list(interest_ids)).delete() return JsonResponse({'success': True})
def remove_interest(request, bounty_id): """Unclaim work from the Bounty. :request method: POST post_id (int): ID of the Bounty. Returns: dict: The success key with a boolean value and accompanying error. """ access_token = request.GET.get('token') if access_token and is_github_token_valid(access_token): helper_handle_access_token(request, access_token) profile_id = request.session.get('profile_id') if not profile_id: return JsonResponse( { 'error': 'You must be authenticated via github to use this feature!' }, status=401) try: bounty = Bounty.objects.get(pk=bounty_id) except Bounty.DoesNotExist: return JsonResponse({'errors': ['Bounty doesn\'t exist!']}, status=401) try: interest = Interest.objects.get(profile_id=profile_id, bounty=bounty) record_user_action( Profile.objects.get(pk=profile_id).handle, 'stop_work', interest) bounty.interested.remove(interest) interest.delete() maybe_market_to_slack(bounty, 'stop_work') maybe_market_to_twitter(bounty, 'stop_work') except Interest.DoesNotExist: return JsonResponse( { 'errors': ['You haven\'t expressed interest on this bounty.'], 'success': False }, status=401) except Interest.MultipleObjectsReturned: interest_ids = bounty.interested \ .filter( profile_id=profile_id, bounty=bounty ).values_list('id', flat=True) \ .order_by('-created') bounty.interested.remove(*interest_ids) Interest.objects.filter(pk__in=list(interest_ids)).delete() return JsonResponse({'success': True})
def uninterested(request, bounty_id, profile_id): """Remove party from given bounty :request method: GET Args: bounty_id (int): ID of the Bounty profile_id (int): ID of the interested profile Returns: dict: The success key with a boolean value and accompanying error. """ session_profile_id = request.session.get('profile_id') if not session_profile_id: return JsonResponse({'error': 'You must be authenticated!'}, status=401) try: bounty = Bounty.objects.get(pk=bounty_id) except Bounty.DoesNotExist: return JsonResponse({'errors': ['Bounty doesn\'t exist!']}, status=401) if not bounty.is_funder(request.session.get('handle').lower()): return JsonResponse( {'error': 'Only bounty funders are allowed to remove users!'}, status=401) try: interest = Interest.objects.get(profile_id=profile_id, bounty=bounty) bounty.interested.remove(interest) maybe_market_to_slack(bounty, 'stop_work') interest.delete() except Interest.DoesNotExist: return JsonResponse( { 'errors': ['Party haven\'t expressed interest on this bounty.'], 'success': False }, status=401) except Interest.MultipleObjectsReturned: interest_ids = bounty.interested \ .filter( profile_id=profile_id, bounty=bounty ).values_list('id', flat=True) \ .order_by('-created') bounty.interested.remove(*interest_ids) Interest.objects.filter(pk__in=list(interest_ids)).delete() profile = Profile.objects.get(id=profile_id) bounty_uninterested(profile.email, bounty, interest) return JsonResponse({'success': True})
def new_interest(request, bounty_id): """Claim Work for a Bounty. :request method: POST Args: post_id (int): ID of the Bounty. Returns: dict: The success key with a boolean value and accompanying error. """ profile_id = request.session.get('profile_id') if not profile_id: return JsonResponse({'error': 'You must be authenticated!'}, status=401) try: bounty = Bounty.objects.get(pk=bounty_id) except Bounty.DoesNotExist: raise Http404 try: Interest.objects.get(profile_id=profile_id, bounty=bounty) return JsonResponse( { 'error': 'You have already expressed interest in this bounty!', 'success': False }, status=401) except Interest.DoesNotExist: interest = Interest.objects.create(profile_id=profile_id) bounty.interested.add(interest) maybe_market_to_slack(bounty, 'start_work') except Interest.MultipleObjectsReturned: bounty_ids = bounty.interested \ .filter(profile_id=profile_id) \ .values_list('id', flat=True) \ .order_by('-created')[1:] Interest.objects.filter(pk__in=list(bounty_ids)).delete() return JsonResponse( { 'error': 'You have already expressed interest in this bounty!', 'success': False }, status=401) return JsonResponse({ 'success': True, 'profile': ProfileSerializer(interest.profile).data })
def process_bounty_changes(old_bounty, new_bounty): """Process legacy bounty changes. Args: old_bounty (dashboard.models.Bounty): The old Bounty object. new_bounty (dashboard.models.Bounty): The new Bounty object. """ # process bounty sync requests did_bsr = False for bsr in BountySyncRequest.objects.filter(processed=False, github_url=new_bounty.github_url): did_bsr = True bsr.processed = True bsr.save() # new bounty if (not old_bounty and new_bounty and new_bounty.is_open) or (not old_bounty.is_open and new_bounty.is_open): event_name = 'new_bounty' elif old_bounty.num_fulfillments < new_bounty.num_fulfillments: event_name = 'work_submitted' elif old_bounty.is_open and not new_bounty.is_open: if new_bounty.status == 'cancelled': event_name = 'killed_bounty' else: event_name = 'work_done' else: event_name = 'unknown_event' print(event_name) # Build profile pairs list if new_bounty.fulfillments.exists(): profile_pairs = build_profile_pairs(new_bounty) # marketing if event_name != 'unknown_event': print("============ posting ==============") did_post_to_twitter = maybe_market_to_twitter(new_bounty, event_name) did_post_to_slack = maybe_market_to_slack(new_bounty, event_name) did_post_to_github = maybe_market_to_github(new_bounty, event_name, profile_pairs) did_post_to_email = maybe_market_to_email(new_bounty, event_name) print("============ done posting ==============") # what happened what_happened = { 'did_bsr': did_bsr, 'did_post_to_email': did_post_to_email, 'did_post_to_github': did_post_to_github, 'did_post_to_slack': did_post_to_slack, 'did_post_to_twitter': did_post_to_twitter, } print("Legacy changes processed: ") pp = pprint.PrettyPrinter(indent=4) pp.pprint(what_happened) else: print('No notifications sent - Legacy Event Type Unknown = did_bsr: ', did_bsr)
def process_bounty_changes(old_bounty, new_bounty, txid): from dashboard.utils import build_profile_pairs profile_pairs = None # process bounty sync requests did_bsr = False for bsr in BountySyncRequest.objects.filter( processed=False, github_url=new_bounty.github_url): did_bsr = True bsr.processed = True bsr.save() # new bounty if (old_bounty is None and new_bounty and new_bounty.is_open) or (not old_bounty.is_open and new_bounty.is_open): event_name = 'new_bounty' elif old_bounty.num_fulfillments < new_bounty.num_fulfillments: event_name = 'work_submitted' elif old_bounty.is_open and not new_bounty.is_open: if new_bounty.status == 'cancelled': event_name = 'killed_bounty' else: event_name = 'work_done' else: event_name = 'unknown_event' print(event_name) # Build profile pairs list if new_bounty.fulfillments.exists(): profile_pairs = build_profile_pairs(new_bounty) # marketing print("============ posting ==============") did_post_to_twitter = maybe_market_to_twitter(new_bounty, event_name) did_post_to_slack = maybe_market_to_slack(new_bounty, event_name) did_post_to_github = maybe_market_to_github(new_bounty, event_name, profile_pairs) did_post_to_email = maybe_market_to_email(new_bounty, event_name) print("============ done posting ==============") # what happened what_happened = { 'did_bsr': did_bsr, 'did_post_to_email': did_post_to_email, 'did_post_to_github': did_post_to_github, 'did_post_to_slack': did_post_to_slack, 'did_post_to_twitter': did_post_to_twitter, } print("changes processed: ") pp = pprint.PrettyPrinter(indent=4) pp.pprint(what_happened)
def process_bounty_changes(old_bounty, new_bounty, txid): # process bounty sync requests did_bsr = False for bsr in BountySyncRequest.objects.filter( processed=False, github_url=new_bounty.github_url): did_bsr = True bsr.processed = True bsr.save() # new bounty null_address = '0x0000000000000000000000000000000000000000' if (old_bounty is None and new_bounty and new_bounty.is_open) or (not old_bounty.is_open and new_bounty.is_open): event_name = 'new_bounty' elif old_bounty.fulfiller_address == null_address and new_bounty.fulfiller_address != null_address: event_name = 'work_submitted' elif old_bounty.is_open and not new_bounty.is_open: if new_bounty.status == 'cancelled': event_name = 'killed_bounty' else: event_name = 'work_done' elif old_bounty.fulfiller_address != null_address and new_bounty.fulfiller_address == null_address: event_name = 'rejected_claim' else: event_name = 'unknown_event' print(event_name) # marketing print("============ posting ==============") did_post_to_twitter = maybe_market_to_twitter(new_bounty, event_name) did_post_to_slack = maybe_market_to_slack(new_bounty, event_name) did_post_to_github = maybe_market_to_github(new_bounty, event_name) did_post_to_email = maybe_market_to_email(new_bounty, event_name) print("============ done posting ==============") # what happened what_happened = { 'did_bsr': did_bsr, 'did_post_to_email': did_post_to_email, 'did_post_to_github': did_post_to_github, 'did_post_to_slack': did_post_to_slack, 'did_post_to_twitter': did_post_to_twitter, } print("changes processed: ") pp = pprint.PrettyPrinter(indent=4) pp.pprint(what_happened)
def handle(self, *args, **options): bounties = Bounty.objects.current().filter( network='mainnet', idx_status='open') if bounties.count() < 3: print('count is only {}. exiting'.format(bounties.count())) return bounty = bounties.order_by('?').first() remarket_bounties = bounties.filter(admin_mark_as_remarket_ready=True) if remarket_bounties.exists(): bounty = remarket_bounties.order_by('?').first() print(bounty) did_tweet = maybe_market_to_twitter(bounty, 'remarket_bounty') did_slack = maybe_market_to_slack(bounty, 'this funded issue could use some action!') print("did tweet", did_tweet) print("did slack", did_slack)
def process_bounty_changes(old_bounty, new_bounty): """Process Bounty changes. Args: old_bounty (dashboard.models.Bounty): The old Bounty object. new_bounty (dashboard.models.Bounty): The new Bounty object. """ from dashboard.utils import build_profile_pairs profile_pairs = None # process bounty sync requests did_bsr = False for bsr in BountySyncRequest.objects.filter( processed=False, github_url=new_bounty.github_url).nocache(): did_bsr = True bsr.processed = True bsr.save() # get json diff json_diff = diff(old_bounty.raw_data, new_bounty.raw_data) if ( old_bounty and new_bounty) else None # new bounty if not old_bounty or (not old_bounty and new_bounty and new_bounty.is_open) or (not old_bounty.is_open and new_bounty and new_bounty.is_open): is_greater_than_x_days_old = new_bounty.web3_created < ( timezone.now() - timezone.timedelta(hours=24)) if is_greater_than_x_days_old and not settings.IS_DEBUG_ENV: msg = f"attempting to create a new bounty ({new_bounty.standard_bounties_id}) when is_greater_than_x_days_old = True" print(msg) raise Exception(msg) event_name = 'new_bounty' elif old_bounty.num_fulfillments < new_bounty.num_fulfillments: event_name = 'work_submitted' elif old_bounty.is_open and not new_bounty.is_open: if new_bounty.status in ['cancelled', 'expired']: event_name = 'killed_bounty' else: event_name = 'work_done' elif old_bounty.value_in_token < new_bounty.value_in_token: event_name = 'increased_bounty' else: event_name = 'unknown_event' logger.info( f'got an unknown event from bounty {old_bounty.pk} => {new_bounty.pk}: {json_diff}' ) print(f"- {event_name} event; diff => {json_diff}") # record a useraction for this record_user_action(event_name, old_bounty, new_bounty) record_bounty_activity(event_name, old_bounty, new_bounty) # Build profile pairs list if new_bounty.fulfillments.exists(): profile_pairs = build_profile_pairs(new_bounty) # marketing if event_name != 'unknown_event': print("============ posting ==============") did_post_to_twitter = maybe_market_to_twitter(new_bounty, event_name) did_post_to_slack = maybe_market_to_slack(new_bounty, event_name) did_post_to_user_slack = maybe_market_to_user_slack( new_bounty, event_name) did_post_to_user_discord = maybe_market_to_user_discord( new_bounty, event_name) did_post_to_github = maybe_market_to_github(new_bounty, event_name, profile_pairs) did_post_to_email = maybe_market_to_email(new_bounty, event_name) print("============ done posting ==============") # what happened what_happened = { 'did_bsr': did_bsr, 'did_post_to_email': did_post_to_email, 'did_post_to_github': did_post_to_github, 'did_post_to_slack': did_post_to_slack, 'did_post_to_user_slack': did_post_to_user_slack, 'did_post_to_user_discord': did_post_to_user_discord, 'did_post_to_twitter': did_post_to_twitter, } print("changes processed: ") pp = pprint.PrettyPrinter(indent=4) pp.pprint(what_happened) else: print('No notifications sent - Event Type Unknown = did_bsr: ', did_bsr)
def new_interest(request, bounty_id): """Claim Work for a Bounty. :request method: POST Args: post_id (int): ID of the Bounty. Returns: dict: The success key with a boolean value and accompanying error. """ profile_id = request.session.get('profile_id') if not profile_id: return JsonResponse( { 'error': 'You must be authenticated via github to use this feature!' }, status=401) try: bounty = Bounty.objects.get(pk=bounty_id) except Bounty.DoesNotExist: raise Http404 num_issues = 3 active_bounties = Bounty.objects.current().filter( idx_status__in=['open', 'started']) num_active = Interest.objects.filter(profile_id=profile_id, bounty__in=active_bounties).count() is_working_on_too_much_stuff = num_active >= num_issues if is_working_on_too_much_stuff: return JsonResponse( { 'error': f'You may only work on max of {num_issues} issues at once.', 'success': False }, status=401) try: Interest.objects.get(profile_id=profile_id, bounty=bounty) return JsonResponse( { 'error': 'You have already expressed interest in this bounty!', 'success': False }, status=401) except Interest.DoesNotExist: interest = Interest.objects.create(profile_id=profile_id) bounty.interested.add(interest) record_user_action( Profile.objects.get(pk=profile_id).handle, 'start_work', interest) maybe_market_to_slack(bounty, 'start_work') except Interest.MultipleObjectsReturned: bounty_ids = bounty.interested \ .filter(profile_id=profile_id) \ .values_list('id', flat=True) \ .order_by('-created')[1:] Interest.objects.filter(pk__in=list(bounty_ids)).delete() return JsonResponse( { 'error': 'You have already expressed interest in this bounty!', 'success': False }, status=401) return JsonResponse({ 'success': True, 'profile': ProfileSerializer(interest.profile).data })
def process_bounty_changes(old_bounty, new_bounty): """Process Bounty changes. Args: old_bounty (dashboard.models.Bounty): The old Bounty object. new_bounty (dashboard.models.Bounty): The new Bounty object. """ from dashboard.utils import build_profile_pairs profile_pairs = None # check for maintainer blocks is_blocked = any([(ele.lower() in new_bounty.github_url.lower()) for ele in BlockedURLFilter.objects.values_list( 'expression', flat=True)]) if is_blocked: raise UnsupportedRepoException( "This repo is not bountyable at the request of the maintainer.") # process bounty sync requests did_bsr = False for bsr in BountySyncRequest.objects.filter( processed=False, github_url=new_bounty.github_url).nocache(): did_bsr = True bsr.processed = True bsr.save() # get json diff json_diff = diff(old_bounty.raw_data, new_bounty.raw_data) if ( old_bounty and new_bounty) else None # new bounty if not old_bounty or (not old_bounty and new_bounty and new_bounty.is_open) or (not old_bounty.is_open and new_bounty and new_bounty.is_open): is_greater_than_x_days_old = new_bounty.web3_created < ( timezone.now() - timezone.timedelta(hours=24)) if is_greater_than_x_days_old and not settings.IS_DEBUG_ENV: msg = f"attempting to create a new bounty ({new_bounty.standard_bounties_id}) when is_greater_than_x_days_old = True" print(msg) raise Exception(msg) event_name = 'new_bounty' elif old_bounty.num_fulfillments < new_bounty.num_fulfillments: event_name = 'work_submitted' elif old_bounty.is_open and not new_bounty.is_open: if new_bounty.status in ['cancelled', 'expired']: event_name = 'killed_bounty' else: event_name = 'work_done' elif old_bounty.value_in_token < new_bounty.value_in_token: event_name = 'increased_bounty' else: event_name = 'unknown_event' logger.info( f'got an unknown event from bounty {old_bounty.pk} => {new_bounty.pk}: {json_diff}' ) print(f"- {event_name} event; diff => {json_diff}") # record a useraction for this record_user_action(event_name, old_bounty, new_bounty) record_bounty_activity(event_name, old_bounty, new_bounty) # Build profile pairs list if new_bounty.fulfillments.exists(): profile_pairs = build_profile_pairs(new_bounty) # Send an Email if this is a LowBall bounty try: if (not old_bounty or old_bounty.value_in_usdt != new_bounty.value_in_usdt): if is_lowball_bounty(new_bounty.value_in_usdt ) and new_bounty.network == 'mainnet': notify_of_lowball_bounty(new_bounty) except Exception as e: logger.error(f'{e} during check for Lowball Bounty') # marketing if event_name != 'unknown_event': print("============ posting ==============") did_post_to_slack = maybe_market_to_slack(new_bounty, event_name) did_post_to_user_slack = maybe_market_to_user_slack( new_bounty, event_name) did_post_to_github = maybe_market_to_github(new_bounty, event_name, profile_pairs) did_post_to_email = maybe_market_to_email(new_bounty, event_name) print("============ done posting ==============") # what happened what_happened = { 'did_bsr': did_bsr, 'did_post_to_email': did_post_to_email, 'did_post_to_github': did_post_to_github, 'did_post_to_slack': did_post_to_slack, 'did_post_to_user_slack': did_post_to_user_slack, 'did_post_to_twitter': False, } print("changes processed: ") pp = pprint.PrettyPrinter(indent=4) pp.pprint(what_happened) else: print('No notifications sent - Event Type Unknown = did_bsr: ', did_bsr)