Ejemplo n.º 1
0
def issue_details(request):
    """Determine the Github issue keywords of the specified Github issue or PR URL.

    Todo:
        * Modify the view to only use the Github API (remove BeautifulSoup).
        * Simplify the view logic.

    Returns:
        JsonResponse: A JSON response containing the Github issue or PR keywords.

    """
    from dashboard.utils import clean_bounty_url
    response = {}
    token = request.GET.get('token', None)
    url = request.GET.get('url')
    url_val = URLValidator()
    hackathon_slug = request.GET.get('hackathon_slug')
    duplicates = request.GET.get('duplicates', False)
    network = request.GET.get('network', 'mainnet')


    if hackathon_slug:
        sponsor_profiles = HackathonEvent.objects.filter(slug__iexact=hackathon_slug).prefetch_related('sponsor_profiles').values_list('sponsor_profiles__handle', flat=True)
        org_issue = org_name(url).lower()

        if org_issue not in sponsor_profiles:
            message = 'This issue is not under any sponsor repository'
            return JsonResponse({'status':'false','message':message}, status=404)

    if duplicates:
        if Bounty.objects.filter(github_url=url, network=network).exists():
            message = 'Bounty already exists for this github issue'
            response = {
                'status': 422,
                'message': message
            }
            return JsonResponse(response, status=422)

    try:
        url_val(url)
    except ValidationError:
        response['message'] = 'invalid arguments'
        return JsonResponse(response)

    if url.lower()[:19] != 'https://github.com/':
        response['message'] = 'invalid arguments'
        return JsonResponse(response)

    url_dict = get_url_dict(clean_bounty_url(url))

    try:
        if url_dict:
            response = get_gh_issue_details(token=token, **url_dict)
        else:
            response['message'] = 'could not parse Github url'
    except Exception as e:
        logger.warning(e)
        message = 'could not pull back remote response'
        return JsonResponse({'status':'false','message':message}, status=404)
    return JsonResponse(response)
Ejemplo n.º 2
0
def issue_details(request):
    """Determine theissue keywords of the specified issue or PR URL.

    Todo:
        * Modify the view to only use the Github API (remove BeautifulSoup).
        * Simplify the view logic.

    Returns:
        JsonResponse: A JSON response containing the issue or PR keywords.

    """
    from dashboard.utils import clean_bounty_url
    response = {}
    token = request.GET.get('token', None)
    url = request.GET.get('url')
    url_val = URLValidator()

    try:
        url_val(url)
    except ValidationError:
        response['message'] = 'invalid arguments'
        return JsonResponse(response)

    if url.lower()[:19] != 'https://github.com/' and url.lower(
    )[:19] != 'https://gitlab.com/':
        response['message'] = 'invalid arguments'
        return JsonResponse(response)

    try:
        url_dict = get_url_dict(clean_bounty_url(url))
        if url_dict:
            logger.info(url_dict)
            response = get_issue_details(token=token, **url_dict)
        else:
            response['message'] = 'could not parse url'
    except Exception as e:
        logger.warning(e)
        response['message'] = 'could not pull back remote response'
    return JsonResponse(response)
Ejemplo n.º 3
0
def create_new_bounty(old_bounties, bounty_payload, bounty_details, bounty_id):
    """Handle new Bounty creation in the event of bounty changes.

    Possible Bounty Stages:
        0: Draft
        1: Active
        2: Dead

    Returns:
        dashboard.models.Bounty: The new Bounty object.

    """
    bounty_issuer = bounty_payload.get('issuer', {})
    metadata = bounty_payload.get('metadata', {})
    # fulfillments metadata will be empty when bounty is first created
    fulfillments = bounty_details.get('fulfillments', {})
    interested_comment_id = None
    submissions_comment_id = None
    interested_comment_id = None

    # start to process out all the bounty data
    url = bounty_payload.get('webReferenceURL')
    if url:
        url = normalize_url(url)
    else:
        raise UnsupportedSchemaException(
            'No webReferenceURL found. Cannot continue!')

    # Check if we have any fulfillments.  If so, check if they are accepted.
    # If there are no fulfillments, accepted is automatically False.
    # Currently we are only considering the latest fulfillment.  Std bounties supports multiple.
    # If any of the fulfillments have been accepted, the bounty is now accepted and complete.
    accepted = any(
        [fulfillment.get('accepted') for fulfillment in fulfillments])

    with transaction.atomic():
        old_bounties = old_bounties.distinct().order_by('created_on')
        latest_old_bounty = None
        token_address = bounty_payload.get(
            'tokenAddress', '0x0000000000000000000000000000000000000000')
        token_name = bounty_payload.get('tokenName', '')
        if not token_name:
            token = addr_to_token(token_address)
            if token:
                token_name = token['name']

        for old_bounty in old_bounties:
            if old_bounty.current_bounty:
                submissions_comment_id = old_bounty.submissions_comment
                interested_comment_id = old_bounty.interested_comment
            old_bounty.current_bounty = False
            old_bounty.save()
            latest_old_bounty = old_bounty

        bounty_kwargs = {
            'is_open':
            True if (bounty_details.get('bountyStage') == 1 and not accepted)
            else False,
            'raw_data':
            bounty_details,
            'metadata':
            metadata,
            'current_bounty':
            True,
            'accepted':
            accepted,
            'interested_comment':
            interested_comment_id,
            'submissions_comment':
            submissions_comment_id,
            'standard_bounties_id':
            bounty_id,
            'num_fulfillments':
            len(fulfillments),
            'value_in_token':
            bounty_details.get('fulfillmentAmount', Decimal(1.0))
        }
        if not latest_old_bounty:
            schemes = bounty_payload.get('schemes', {})
            bounty_kwargs.update({
                # info to xfr over from latest_old_bounty as override fields (this is because sometimes
                # ppl dont login when they first submit issue and it needs to be overridden)
                'web3_created':
                timezone.make_aware(timezone.datetime.fromtimestamp(
                    bounty_payload.get('created')),
                                    timezone=UTC),
                'github_url':
                url,
                'token_name':
                token_name,
                'token_address':
                token_address,
                'privacy_preferences':
                bounty_payload.get('privacy_preferences', {}),
                'expires_date':
                timezone.make_aware(timezone.datetime.fromtimestamp(
                    bounty_details.get('deadline')),
                                    timezone=UTC),
                'title':
                bounty_payload.get('title', ''),
                'issue_description':
                bounty_payload.get('description', ' '),
                'balance':
                bounty_details.get('balance'),
                'contract_address':
                bounty_details.get('token'),
                'network':
                bounty_details.get('network'),
                'bounty_type':
                metadata.get('bountyType', ''),
                'funding_organisation':
                metadata.get('fundingOrganisation', ''),
                'project_length':
                metadata.get('projectLength', ''),
                'estimated_hours':
                metadata.get('estimatedHours'),
                'experience_level':
                metadata.get('experienceLevel', ''),
                'project_type':
                schemes.get('project_type', 'traditional'),
                'permission_type':
                schemes.get('permission_type', 'permissionless'),
                'attached_job_description':
                bounty_payload.get('hiring', {}).get('jobDescription', None),
                'is_featured':
                metadata.get('is_featured', False),
                'bounty_owner_github_username':
                bounty_issuer.get('githubUsername', ''),
                'bounty_owner_address':
                bounty_issuer.get('address', ''),
                'bounty_owner_email':
                bounty_issuer.get('email', ''),
                'bounty_owner_name':
                bounty_issuer.get('name', ''),
                'admin_override_suspend_auto_approval':
                not schemes.get('auto_approve_workers', True),
            })
        else:
            latest_old_bounty_dict = latest_old_bounty.to_standard_dict(
                fields=[
                    'web3_created',
                    'github_url',
                    'token_name',
                    'token_address',
                    'privacy_preferences',
                    'expires_date',
                    'title',
                    'issue_description',
                    'balance',
                    'contract_address',
                    'network',
                    'bounty_type',
                    'project_length',
                    'experience_level',
                    'project_type',
                    'permission_type',
                    'attached_job_description',
                    'bounty_owner_github_username',
                    'bounty_owner_address',
                    'bounty_owner_email',
                    'bounty_owner_name',
                    'github_comments',
                    'override_status',
                    'last_comment_date',
                    'snooze_warnings_for_days',
                    'admin_override_and_hide',
                    'admin_override_suspend_auto_approval',
                    'admin_mark_as_remarket_ready',
                    'funding_organisation',
                    'bounty_reserved_for_user',
                    'is_featured',
                ], )
            if latest_old_bounty_dict['bounty_reserved_for_user']:
                latest_old_bounty_dict[
                    'bounty_reserved_for_user'] = Profile.objects.get(
                        pk=latest_old_bounty_dict['bounty_reserved_for_user'])
            bounty_kwargs.update(latest_old_bounty_dict)

        try:
            new_bounty = Bounty.objects.create(**bounty_kwargs)
            new_bounty.fetch_issue_item()
            try:
                issue_kwargs = get_url_dict(new_bounty.github_url)
                new_bounty.github_issue_details = get_gh_issue_details(
                    **issue_kwargs)
            except Exception as e:
                logger.error(e)

            # migrate data objects from old bounty
            if latest_old_bounty:
                # Pull the interested parties off the last old_bounty
                for interest in latest_old_bounty.interested.all().nocache():
                    new_bounty.interested.add(interest)

                # pull the activities off the last old bounty
                for activity in latest_old_bounty.activities.all().nocache():
                    new_bounty.activities.add(activity)

            bounty_reserved_for_user = metadata.get('reservedFor', '')
            if bounty_reserved_for_user:
                new_bounty.reserved_for_user_handle = bounty_reserved_for_user
                new_bounty.save()
                if new_bounty.bounty_reserved_for_user:
                    # notify a user that a bounty has been reserved for them
                    new_reserved_issue('*****@*****.**',
                                       new_bounty.bounty_reserved_for_user,
                                       new_bounty)

            # set cancel date of this bounty
            canceled_on = latest_old_bounty.canceled_on if latest_old_bounty and latest_old_bounty.canceled_on else None
            if not canceled_on and new_bounty.status == 'cancelled':
                canceled_on = timezone.now()
            if canceled_on:
                new_bounty.canceled_on = canceled_on
                new_bounty.save()

        except Exception as e:
            print(e, 'encountered during new bounty creation for:', url)
            logger.error(
                f'{e} encountered during new bounty creation for: {url}')
            new_bounty = None

        if fulfillments:
            handle_bounty_fulfillments(fulfillments, new_bounty,
                                       latest_old_bounty)
            for inactive in Bounty.objects.filter(
                    current_bounty=False,
                    github_url=url).nocache().order_by('-created_on'):
                BountyFulfillment.objects.filter(
                    bounty_id=inactive.id).nocache().delete()
    return new_bounty
Ejemplo n.º 4
0
def merge_bounty(latest_old_bounty,
                 new_bounty,
                 metadata,
                 bounty_details,
                 verbose=True):
    if verbose:
        print('new bounty is:{}'.format(new_bounty.to_standard_dict()))
    new_bounty.fetch_issue_item()
    try:
        issue_kwargs = get_url_dict(new_bounty.github_url)
        new_bounty.github_issue_details = get_gh_issue_details(**issue_kwargs)

    except Exception as e:
        logger.error(e)

    if latest_old_bounty and latest_old_bounty.event:
        new_bounty.event = latest_old_bounty.event
        new_bounty.save()
    else:
        event_tag = metadata.get('eventTag', '')
        if event_tag:
            try:
                evt = HackathonEvent.objects.filter(
                    name__iexact=event_tag).latest('id')
                new_bounty.event = evt
                new_bounty.save()
            except Exception as e:
                logger.error(e)

    bounty_invitees = metadata.get('invite', '')
    if bounty_invitees and not latest_old_bounty:
        from marketing.mails import share_bounty
        from dashboard.utils import get_bounty_invite_url
        emails = []
        inviter = Profile.objects.get(
            handle=new_bounty.bounty_owner_github_username)
        invite_url = get_bounty_invite_url(inviter, new_bounty.id)
        msg = "Check out this bounty that pays out " + \
            str(new_bounty.get_value_true) + new_bounty.token_name + invite_url
        for keyword in new_bounty.keywords_list:
            msg += " #" + keyword
        for user_id in bounty_invitees:
            profile = Profile.objects.get(id=int(user_id))
            if not profile.user:
                continue
            bounty_invite = BountyInvites.objects.create(status='pending')
            bounty_invite.bounty.add(new_bounty)
            bounty_invite.inviter.add(inviter.user)
            bounty_invite.invitee.add(profile.user)
            emails.append(profile.email)
        try:
            share_bounty(emails, msg, inviter, invite_url, False)
            response = {
                'status': 200,
                'msg': 'email_sent',
            }
        except Exception as e:
            logging.exception(e)
            response = {
                'status': 500,
                'msg': 'Email not sent',
            }
    # migrate data objects from old bounty
    if latest_old_bounty:
        # Pull the interested parties off the last old_bounty
        for interest in latest_old_bounty.interested.all().nocache():
            new_bounty.interested.add(interest)

        # pull the activities off the last old bounty
        for activity in latest_old_bounty.activities.all().nocache():
            new_bounty.activities.add(activity)

    bounty_reserved_for_user = metadata.get('reservedFor', '')
    release_to_public_after = metadata.get('releaseAfter', '')
    if bounty_reserved_for_user and release_to_public_after:
        new_bounty.reserved_for_user_from = timezone.now()
        if release_to_public_after == "3-days":
            new_bounty.reserved_for_user_expiration = new_bounty.reserved_for_user_from + timezone.timedelta(
                days=3)
        elif release_to_public_after == "1-week":
            new_bounty.reserved_for_user_expiration = new_bounty.reserved_for_user_from + timezone.timedelta(
                weeks=1)

        new_bounty.reserved_for_user_handle = bounty_reserved_for_user
        new_bounty.save()
        if new_bounty.bounty_reserved_for_user and new_bounty.status == 'reserved':
            # notify a user that a bounty has been reserved for them
            new_reserved_issue('*****@*****.**',
                               new_bounty.bounty_reserved_for_user, new_bounty)

    # set cancel date of this bounty
    canceled_on = latest_old_bounty.canceled_on if latest_old_bounty and latest_old_bounty.canceled_on else None
    if not canceled_on and new_bounty.status == 'cancelled':
        canceled_on = timezone.now()
    if canceled_on:
        new_bounty.canceled_on = canceled_on
        new_bounty.save()

    # migrate fulfillments, and only take the ones from
    # fulfillments metadata will be empty when bounty is first created
    fulfillments = bounty_details.get('fulfillments', {})
    if fulfillments:
        handle_bounty_fulfillments(fulfillments, new_bounty, latest_old_bounty)
        url = normalize_url(new_bounty.github_url)
        for inactive in Bounty.objects.filter(
                current_bounty=False,
                github_url=url).nocache().order_by('-created_on'):
            BountyFulfillment.objects.filter(
                bounty_id=inactive.id).nocache().delete()

    # preserve featured status for bounties where it was set manually
    new_bounty.is_featured = True if latest_old_bounty and latest_old_bounty.is_featured is True else False
    if new_bounty.is_featured == True:
        new_bounty.save()

    if latest_old_bounty:
        latest_old_bounty.current_bounty = False
        latest_old_bounty.save()
Ejemplo n.º 5
0
def create_new_bounty(old_bounties, bounty_payload, bounty_details, bounty_id):
    """Handle new Bounty creation in the event of bounty changes.

    Possible Bounty Stages:
        0: Draft
        1: Active
        2: Dead

    Returns:
        dashboard.models.Bounty: The new Bounty object.

    """
    bounty_issuer = bounty_payload.get('issuer', {})
    metadata = bounty_payload.get('metadata', {})
    # fulfillments metadata will be empty when bounty is first created
    fulfillments = bounty_details.get('fulfillments', {})
    interested_comment_id = None
    submissions_comment_id = None
    interested_comment_id = None

    # start to process out all the bounty data
    url = bounty_payload.get('webReferenceURL')
    if url:
        url = normalize_url(url)
    else:
        raise UnsupportedSchemaException(
            'No webReferenceURL found. Cannot continue!')

    # check conditions for private repos
    if metadata.get('repo_type', None) == 'private' and \
        bounty_payload.get('schemes', {}).get('permission_type', 'permissionless') != 'approval' and \
            bounty_payload.get('schemes', {}).get('project_type', 'traditional') != 'traditional':
        raise UnsupportedSchemaException(
            'The project type or permission does not match for private repo')

    # Check if we have any fulfillments.  If so, check if they are accepted.
    # If there are no fulfillments, accepted is automatically False.
    # Currently we are only considering the latest fulfillment.  Std bounties supports multiple.
    # If any of the fulfillments have been accepted, the bounty is now accepted and complete.
    accepted = any(
        [fulfillment.get('accepted') for fulfillment in fulfillments])
    print('create new bounty with payload:{}'.format(bounty_payload))

    with transaction.atomic():
        old_bounties = old_bounties.distinct().order_by('created_on')
        latest_old_bounty = None
        token_address = bounty_payload.get(
            'tokenAddress', '0x0000000000000000000000000000000000000000')
        token_name = bounty_payload.get('tokenName', '')
        if not token_name:
            token = addr_to_token(token_address)
            if token:
                token_name = token['name']

        for old_bounty in old_bounties:
            if old_bounty.current_bounty:
                submissions_comment_id = old_bounty.submissions_comment
                interested_comment_id = old_bounty.interested_comment
            old_bounty.current_bounty = False
            old_bounty.save()
            latest_old_bounty = old_bounty

        bounty_kwargs = {
            'is_open':
            True if (bounty_details.get('bountyStage') == 1 and not accepted)
            else False,
            'raw_data':
            bounty_details,
            'metadata':
            metadata,
            'current_bounty':
            True,
            'accepted':
            accepted,
            'interested_comment':
            interested_comment_id,
            'submissions_comment':
            submissions_comment_id,
            'standard_bounties_id':
            bounty_id,
            'num_fulfillments':
            len(fulfillments),
            'value_in_token':
            bounty_details.get('fulfillmentAmount', Decimal(1.0)),
            'fee_tx_id':
            bounty_payload.get('fee_tx_id', '0x0'),
            'fee_amount':
            bounty_payload.get('fee_amount', 0)
        }
        if not latest_old_bounty:
            print("no latest old bounty")
            schemes = bounty_payload.get('schemes', {})
            unsigned_nda = None
            if bounty_payload.get('unsigned_nda', None):
                unsigned_nda = BountyDocuments.objects.filter(
                    pk=bounty_payload.get('unsigned_nda')).first()
            bounty_kwargs.update({
                # info to xfr over from latest_old_bounty as override fields (this is because sometimes
                # ppl dont login when they first submit issue and it needs to be overridden)
                'web3_created':
                timezone.make_aware(timezone.datetime.fromtimestamp(
                    bounty_payload.get('created')),
                                    timezone=UTC),
                'github_url':
                url,
                'token_name':
                token_name,
                'token_address':
                token_address,
                'privacy_preferences':
                bounty_payload.get('privacy_preferences', {}),
                'expires_date':
                timezone.make_aware(timezone.datetime.fromtimestamp(
                    bounty_details.get('deadline')),
                                    timezone=UTC),
                'title':
                bounty_payload.get('title', ''),
                'issue_description':
                bounty_payload.get('description', ' '),
                'balance':
                bounty_details.get('balance'),
                'contract_address':
                bounty_details.get('token'),
                'network':
                bounty_details.get('network'),
                'bounty_type':
                metadata.get('bountyType', ''),
                'funding_organisation':
                metadata.get('fundingOrganisation', ''),
                'project_length':
                metadata.get('projectLength', ''),
                'estimated_hours':
                metadata.get('estimatedHours'),
                'experience_level':
                metadata.get('experienceLevel', ''),
                'project_type':
                schemes.get('project_type', 'traditional'),
                'permission_type':
                schemes.get('permission_type', 'permissionless'),
                'attached_job_description':
                bounty_payload.get('hiring', {}).get('jobDescription', None),
                'is_featured':
                metadata.get('is_featured', False),
                'featuring_date':
                timezone.make_aware(timezone.datetime.fromtimestamp(
                    metadata.get('featuring_date', 0)),
                                    timezone=UTC),
                'repo_type':
                metadata.get('repo_type', 'public'),
                'unsigned_nda':
                unsigned_nda,
                'bounty_owner_github_username':
                bounty_issuer.get('githubUsername', ''),
                'bounty_owner_address':
                bounty_issuer.get('address', ''),
                'bounty_owner_email':
                bounty_issuer.get('email', ''),
                'bounty_owner_name':
                bounty_issuer.get('name', ''),
                'admin_override_suspend_auto_approval':
                not schemes.get('auto_approve_workers', True),
                'fee_tx_id':
                bounty_payload.get('fee_tx_id', '0x0'),
                'fee_amount':
                bounty_payload.get('fee_amount', 0)
            })
        else:
            print('latest old bounty found {}'.format(latest_old_bounty))
            latest_old_bounty_dict = latest_old_bounty.to_standard_dict(
                fields=[
                    'web3_created', 'github_url', 'token_name',
                    'token_address', 'privacy_preferences', 'expires_date',
                    'title', 'issue_description', 'balance',
                    'contract_address', 'network', 'bounty_type',
                    'project_length', 'experience_level', 'project_type',
                    'permission_type', 'attached_job_description',
                    'bounty_owner_github_username', 'bounty_owner_address',
                    'bounty_owner_email', 'bounty_owner_name',
                    'github_comments', 'override_status', 'last_comment_date',
                    'snooze_warnings_for_days', 'admin_override_and_hide',
                    'admin_override_suspend_auto_approval',
                    'admin_mark_as_remarket_ready', 'funding_organisation',
                    'bounty_reserved_for_user', 'is_featured',
                    'featuring_date', 'fee_tx_id', 'fee_amount', 'repo_type',
                    'unsigned_nda'
                ], )
            if latest_old_bounty_dict['bounty_reserved_for_user']:
                latest_old_bounty_dict[
                    'bounty_reserved_for_user'] = Profile.objects.get(
                        pk=latest_old_bounty_dict['bounty_reserved_for_user'])
            if latest_old_bounty_dict.get('bounty_owner_profile'):
                latest_old_bounty_dict[
                    'bounty_owner_profile'] = Profile.objects.get(
                        pk=latest_old_bounty_dict['bounty_owner_profile'])
            if latest_old_bounty_dict['unsigned_nda']:
                latest_old_bounty_dict[
                    'unsigned_nda'] = BountyDocuments.objects.filter(
                        pk=latest_old_bounty_dict['unsigned_nda']).first()
            bounty_kwargs.update(latest_old_bounty_dict)

        try:
            print('new bounty with kwargs:{}'.format(bounty_kwargs))
            new_bounty = Bounty.objects.create(**bounty_kwargs)
            print('new bounty is:{}'.format(new_bounty.to_standard_dict()))
            new_bounty.fetch_issue_item()
            try:
                issue_kwargs = get_url_dict(new_bounty.github_url)
                new_bounty.github_issue_details = get_gh_issue_details(
                    **issue_kwargs)

            except Exception as e:
                logger.error(e)

            event_tag = metadata.get('eventTag', '')
            if event_tag:
                try:
                    evt = HackathonEvent.objects.filter(
                        name__iexact=event_tag).latest('id')
                    new_bounty.event = evt
                    new_bounty.save()
                except Exception as e:
                    logger.error(e)

            bounty_invitees = metadata.get('invite', '')
            if bounty_invitees and not latest_old_bounty:
                from marketing.mails import share_bounty
                from dashboard.utils import get_bounty_invite_url
                emails = []
                inviter = Profile.objects.get(
                    handle=new_bounty.bounty_owner_github_username)
                invite_url = get_bounty_invite_url(inviter, new_bounty.id)
                msg = "Check out this bounty that pays out " + \
                    str(new_bounty.get_value_true) + new_bounty.token_name + invite_url
                for keyword in new_bounty.keywords_list:
                    msg += " #" + keyword
                for user_id in bounty_invitees:
                    profile = Profile.objects.get(id=int(user_id))
                    bounty_invite = BountyInvites.objects.create(
                        status='pending')
                    bounty_invite.bounty.add(new_bounty)
                    bounty_invite.inviter.add(inviter.user)
                    bounty_invite.invitee.add(profile.user)
                    emails.append(profile.email)
                try:
                    share_bounty(emails, msg, inviter, invite_url, False)
                    response = {
                        'status': 200,
                        'msg': 'email_sent',
                    }
                except Exception as e:
                    logging.exception(e)
                    response = {
                        'status': 500,
                        'msg': 'Email not sent',
                    }
            # migrate data objects from old bounty
            if latest_old_bounty:
                # Pull the interested parties off the last old_bounty
                for interest in latest_old_bounty.interested.all().nocache():
                    new_bounty.interested.add(interest)

                # pull the activities off the last old bounty
                for activity in latest_old_bounty.activities.all().nocache():
                    new_bounty.activities.add(activity)

            bounty_reserved_for_user = metadata.get('reservedFor', '')
            if bounty_reserved_for_user:
                new_bounty.reserved_for_user_handle = bounty_reserved_for_user
                new_bounty.save()
                if new_bounty.bounty_reserved_for_user:
                    # notify a user that a bounty has been reserved for them
                    new_reserved_issue('*****@*****.**',
                                       new_bounty.bounty_reserved_for_user,
                                       new_bounty)

            # set cancel date of this bounty
            canceled_on = latest_old_bounty.canceled_on if latest_old_bounty and latest_old_bounty.canceled_on else None
            if not canceled_on and new_bounty.status == 'cancelled':
                canceled_on = timezone.now()
            if canceled_on:
                new_bounty.canceled_on = canceled_on
                new_bounty.save()

            # preserve featured status for bounties where it was set manually
            new_bounty.is_featured = True if latest_old_bounty and latest_old_bounty.is_featured is True else False
            if new_bounty.is_featured == True:
                new_bounty.save()

        except Exception as e:
            print(e, 'encountered during new bounty creation for:', url)
            logger.error(
                f'{e} encountered during new bounty creation for: {url}')
            new_bounty = None

        if fulfillments:
            handle_bounty_fulfillments(fulfillments, new_bounty,
                                       latest_old_bounty)
            for inactive in Bounty.objects.filter(
                    current_bounty=False,
                    github_url=url).nocache().order_by('-created_on'):
                BountyFulfillment.objects.filter(
                    bounty_id=inactive.id).nocache().delete()
    return new_bounty
Ejemplo n.º 6
0
def create_new_bounty(old_bounties, bounty_payload, bounty_details, bounty_id):
    """Handle new Bounty creation in the event of bounty changes.

    Possible Bounty Stages:
        0: Draft
        1: Active
        2: Dead

    Returns:
        dashboard.models.Bounty: The new Bounty object.

    """
    bounty_issuer = bounty_payload.get('issuer', {})
    metadata = bounty_payload.get('metadata', {})
    # fulfillments metadata will be empty when bounty is first created
    fulfillments = bounty_details.get('fulfillments', {})
    interested_comment_id = None
    submissions_comment_id = None
    interested_comment_id = None

    # start to process out all the bounty data
    url = bounty_payload.get('webReferenceURL')
    if url:
        url = normalize_url(url)
    else:
        raise UnsupportedSchemaException(
            'No webReferenceURL found. Cannot continue!')

    # Check if we have any fulfillments.  If so, check if they are accepted.
    # If there are no fulfillments, accepted is automatically False.
    # Currently we are only considering the latest fulfillment.  Std bounties supports multiple.
    # If any of the fulfillments have been accepted, the bounty is now accepted and complete.
    accepted = any(
        [fulfillment.get('accepted') for fulfillment in fulfillments])

    with transaction.atomic():
        old_bounties = old_bounties.distinct().order_by('created_on')
        latest_old_bounty = None
        token_address = bounty_payload.get(
            'tokenAddress', '0x0000000000000000000000000000000000000000')
        token_name = bounty_payload.get('tokenName', '')
        if not token_name:
            token = addr_to_token(token_address)
            if token:
                token_name = token['name']

        for old_bounty in old_bounties:
            if old_bounty.current_bounty:
                submissions_comment_id = old_bounty.submissions_comment
                interested_comment_id = old_bounty.interested_comment
            old_bounty.current_bounty = False
            old_bounty.save()
            latest_old_bounty = old_bounty
        try:
            new_bounty = Bounty.objects.create(
                is_open=True if (bounty_details.get('bountyStage') == 1
                                 and not accepted) else False,
                raw_data=bounty_details,
                metadata=metadata,
                current_bounty=True,
                accepted=accepted,
                interested_comment=interested_comment_id,
                submissions_comment=submissions_comment_id,
                # These fields are after initial bounty creation, in bounty_details.js
                standard_bounties_id=bounty_id,
                num_fulfillments=len(fulfillments),
                value_in_token=bounty_details.get('fulfillmentAmount'),
                # info to xfr over from latest_old_bounty as override fields (this is because sometimes ppl dont login when they first submit issue and it needs to be overridden)
                web3_created=timezone.make_aware(
                    timezone.datetime.fromtimestamp(
                        bounty_payload.get('created')),
                    timezone=UTC)
                if not latest_old_bounty else latest_old_bounty.web3_created,
                github_url=url
                if not latest_old_bounty else latest_old_bounty.github_url,
                token_name=token_name
                if not latest_old_bounty else latest_old_bounty.token_name,
                token_address=token_address
                if not latest_old_bounty else latest_old_bounty.token_address,
                privacy_preferences=bounty_payload.get(
                    'privacy_preferences', {}) if not latest_old_bounty else
                latest_old_bounty.privacy_preferences,
                expires_date=timezone.make_aware(
                    timezone.datetime.fromtimestamp(
                        bounty_details.get('deadline')),
                    timezone=UTC)
                if not latest_old_bounty else latest_old_bounty.expires_date,
                title=bounty_payload.get('title', '')
                if not latest_old_bounty else latest_old_bounty.title,
                issue_description=bounty_payload.get('description', ' ') if
                not latest_old_bounty else latest_old_bounty.issue_description,
                balance=bounty_details.get('balance')
                if not latest_old_bounty else latest_old_bounty.balance,
                contract_address=bounty_details.get('token') if
                not latest_old_bounty else latest_old_bounty.contract_address,
                network=bounty_details.get('network')
                if not latest_old_bounty else latest_old_bounty.network,
                bounty_type=metadata.get('bountyType', '')
                if not latest_old_bounty else latest_old_bounty.bounty_type,
                project_length=metadata.get('projectLength', '')
                if not latest_old_bounty else latest_old_bounty.project_length,
                experience_level=metadata.get('experienceLevel', '') if
                not latest_old_bounty else latest_old_bounty.experience_level,
                project_type=bounty_payload.get('schemes', {}).get(
                    'project_type', 'traditional')
                if not latest_old_bounty else latest_old_bounty.project_type,
                permission_type=bounty_payload.get('schemes', {}).get(
                    'permission_type', 'permissionless') if
                not latest_old_bounty else latest_old_bounty.permission_type,
                attached_job_description=bounty_payload.get('hiring', {}).get(
                    'jobDescription', None) if not latest_old_bounty else
                latest_old_bounty.attached_job_description,
                bounty_owner_github_username=bounty_issuer.get(
                    'githubUsername', '') if not latest_old_bounty else
                latest_old_bounty.bounty_owner_github_username,
                bounty_owner_address=bounty_issuer.get('address', '')
                if not latest_old_bounty else
                latest_old_bounty.bounty_owner_address,
                bounty_owner_email=bounty_issuer.get('email', '')
                if not latest_old_bounty else
                latest_old_bounty.bounty_owner_email,
                bounty_owner_name=bounty_issuer.get('name', '') if
                not latest_old_bounty else latest_old_bounty.bounty_owner_name,
                # info to xfr over from latest_old_bounty
                github_comments=latest_old_bounty.github_comments
                if latest_old_bounty else 0,
                override_status=latest_old_bounty.override_status
                if latest_old_bounty else '',
                last_comment_date=latest_old_bounty.last_comment_date
                if latest_old_bounty else None,
                snooze_warnings_for_days=latest_old_bounty.
                snooze_warnings_for_days if latest_old_bounty else 0,
                admin_override_and_hide=latest_old_bounty.
                admin_override_and_hide if latest_old_bounty else 0,
                admin_override_suspend_auto_approval=latest_old_bounty.
                admin_override_suspend_auto_approval
                if latest_old_bounty else 0,
                admin_mark_as_remarket_ready=latest_old_bounty.
                admin_mark_as_remarket_ready if latest_old_bounty else 0,
            )
            new_bounty.fetch_issue_item()
            try:
                issue_kwargs = get_url_dict(new_bounty.github_url)
                new_bounty.github_issue_details = get_gh_issue_details(
                    **issue_kwargs)
            except Exception as e:
                logger.error(e)

            # migrate data objects from old bounty
            if latest_old_bounty:
                # Pull the interested parties off the last old_bounty
                for interest in latest_old_bounty.interested.all():
                    new_bounty.interested.add(interest)

                # pull the activities off the last old bounty
                for activity in latest_old_bounty.activities.all():
                    new_bounty.activities.add(activity)

            # set cancel date of this bounty
            canceled_on = latest_old_bounty.canceled_on if latest_old_bounty and latest_old_bounty.canceled_on else None
            if not canceled_on and new_bounty.status == 'cancelled':
                canceled_on = timezone.now()
            if canceled_on:
                new_bounty.canceled_on = canceled_on
                new_bounty.save()

        except Exception as e:
            print(e, 'encountered during new bounty creation for:', url)
            logging.error(
                f'{e} encountered during new bounty creation for: {url}')
            new_bounty = None

        if fulfillments:
            handle_bounty_fulfillments(fulfillments, new_bounty,
                                       latest_old_bounty)
            for inactive in Bounty.objects.filter(
                    current_bounty=False,
                    github_url=url).order_by('-created_on'):
                BountyFulfillment.objects.filter(
                    bounty_id=inactive.id).delete()
    return new_bounty