示例#1
0
def process_accesscode_request(request, pk):

    obj = WhitepaperAccessRequest.objects.get(pk=pk)
    context = {
        'obj': obj,
    }

    if obj.processed:
        raise

    if request.POST.get('submit', False):
        invitecode = token_hex(16)[:29]

        AccessCodes.objects.create(
            invitecode=invitecode,
            maxuses=1,
        )
        obj.processed = True
        obj.save()

        from_email = settings.PERSONAL_CONTACT_EMAIL
        to_email = obj.email
        cur_language = translation.get_language()
        try:
            setup_lang(to_email)
            subject = request.POST.get('subject')
            body = request.POST.get('body').replace('[code]', invitecode)
            send_mail(from_email, to_email, subject, body, from_name=_("Kevin from Gitcoin.co"))
            messages.success(request, _('Invite sent'))
        finally:
            translation.activate(cur_language)

        return redirect('/_administration/tdi/whitepaperaccessrequest/?processed=False')

    return TemplateResponse(request, 'process_accesscode_request.html', context)
示例#2
0
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 = '*****@*****.**'
    cc_emails = '*****@*****.**'
    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'],
                  cc_emails=cc_emails)
    finally:
        translation.activate(cur_language)
示例#3
0
文件: tasks.py 项目: ollutr/web
def bounty_emails(self, emails, msg, profile_handle, invite_url=None, kudos_invite=False, retry: bool = True) -> None:
    """
    :param self:
    :param emails:
    :param msg:
    :param profile_handle:
    :param invite_url:
    :param kudos_invite:
    :return:
    """
    with redis.lock("tasks:bounty_email:%s" % invite_url, timeout=LOCK_TIMEOUT):
        # need to look at how to send bulk emails with SG
        profile = Profile.objects.get(handle=profile_handle.lower())
        try:
            for email in emails:
                to_email = email
                from_email = settings.CONTACT_EMAIL
                subject = "You have been invited to work on a bounty."
                html, text = render_share_bounty(to_email, msg, profile, invite_url, kudos_invite)
                send_mail(
                    from_email,
                    to_email,
                    subject,
                    text,
                    html,
                    from_name=f"@{profile.handle}",
                    categories=['transactional', func_name()],
                )

        except ConnectionError as exc:
            logger.info(str(exc))
            logger.info("Retrying connection")
            self.retry(countdown=30)
        except Exception as e:
            logger.error(str(e))
示例#4
0
def send_ptoken_redemption_accepted(profile, ptoken, redemption):
    from_email = settings.CONTACT_EMAIL
    to_email = profile.email
    if not to_email:
        if profile and profile.user:
            to_email = profile.user.email
    if not to_email:
        return

    cur_language = translation.get_language()

    try:
        setup_lang(to_email)
        html, text, subject = render_ptoken_redemption_accepted(
            ptoken, redemption)

        if not should_suppress_notification_email(to_email,
                                                  'personal_token_redemption'):
            send_mail(from_email,
                      to_email,
                      subject,
                      text,
                      html,
                      categories=['transactional',
                                  func_name()])
    finally:
        translation.activate(cur_language)
示例#5
0
def whitepaper_new(request, ratelimited=False):

    context = {
        'active': 'whitepaper',
        'title': _('Whitepaper'),
        'minihero': _('Whitepaper'),
        'suppress_logo': True,
    }
    if not request.POST.get('submit', False):
        return TemplateResponse(request, 'whitepaper_new.html', context)

    if ratelimited:
        context['msg'] = _(
            "You're ratelimited. Please contact [email protected]")
        return TemplateResponse(request, 'whitepaper_accesscode.html', context)

    context['role'] = request.POST.getlist('role')
    context['email'] = request.POST.get('email')
    context['comments'] = request.POST.get('comments')
    context['success'] = True
    ip = get_ip(request)
    body = gettext("""
Email: {} \n
Role: {}\n
Comments: {}\n
IP: {}\n

https://gitcoin.co/_administration/tdi/whitepaperaccessrequest/

    """).format(context['email'], context['role'], context['comments'], ip)
    send_mail(settings.CONTACT_EMAIL, settings.CONTACT_EMAIL,
              _("New Whitepaper Request"), str(body))

    WhitepaperAccessRequest.objects.create(
        email=context['email'],
        role=context['role'],
        comments=context['comments'],
        ip=ip,
    )

    for code in AccessCodes.objects.all():
        print(code)

    invite_to_slack(context['email'])

    valid_email = True
    try:
        validate_email(request.POST.get('email', False))
    except ValidationError:
        valid_email = False

    if not request.POST.get('email', False) or not valid_email:
        context['msg'] = _("Invalid Email. Please contact [email protected]")
        context['success'] = False
        return TemplateResponse(request, 'whitepaper_new.html', context)

    context['msg'] = _(
        "Your request has been sent.  <a href=/slack>Meantime, why don't you check out the slack channel?</a>"
    )
    return TemplateResponse(request, 'whitepaper_new.html', context)
示例#6
0
    def handle(self, *args, **options):
        bounties = Bounty.objects.filter(
            network='mainnet',
            current_bounty=True,
            web3_created__gte=options['start_date'],
            web3_created__lte=options['end_date']).order_by(
                'web3_created', 'id')

        tips = Tip.objects.filter(
            network='mainnet',
            created_on__gte=options['start_date'],
            created_on__lte=options['end_date']).order_by('created_on', 'id')

        formatted_bounties = imap(self.format_bounty, bounties)
        formatted_tips = imap(self.format_tip, tips)

        csvfile = StringIO.StringIO()
        csvwriter = csv.DictWriter(
            csvfile,
            fieldnames=[
                'type', 'created_on', 'last_activity', 'amount',
                'denomination', 'amount_eth', 'amount_usdt', 'from_address',
                'claimee_address', 'repo', 'from_username',
                'fulfiller_github_username', 'status', 'comments'
            ])
        csvwriter.writeheader()

        has_rows = False
        for item in itermerge(formatted_bounties, formatted_tips,
                              lambda x: x['created_on']):
            has_rows = True
            csvwriter.writerow(item)

        start = options['start_date'].strftime(DATE_FORMAT_HYPHENATED)
        end = options['end_date'].strftime(DATE_FORMAT_HYPHENATED)
        now = str(datetime.datetime.now())
        if has_rows:
            subject = 'Gitcoin Activity report from %s to %s' % (start, end)

            url = self.upload_to_s3(
                'activity_report_%s_%s_generated_on_%s.csv' %
                (start, end, now), csvfile.getvalue())
            body = '<a href="%s">%s</a>' % (url, url)
            print(url)

            send_mail(settings.CONTACT_EMAIL,
                      settings.CONTACT_EMAIL,
                      subject,
                      body='',
                      html=body,
                      add_bcc=False)

            self.stdout.write(
                self.style.SUCCESS('Sent activity report from %s to %s to %s' %
                                   (start, end, settings.CONTACT_EMAIL)))
        else:
            self.stdout.write(
                self.style.WARNING('No activity from %s to %s to report' %
                                   (start, end)))
示例#7
0
def maybe_market_kudos_to_email(kudos_transfer):
    """Send an email for the specified Kudos.  The general flow of this function:

        - 1. Decide if we are sending it
        - 2. Generate subject
        - 3. Render email
        - 4. Send email
        - 5. Do translation

    Args:
        kudos_transfer (kudos.models.KudosTransfer): The Kudos Email object to be marketed.

    Returns:
        bool: Whether or not the email notification was sent successfully.

    """

    # 1. Decide if we are sending it
    if kudos_transfer.network != settings.ENABLE_NOTIFICATIONS_ON_NETWORK:
        logger.warning('Notifications are disabled.  Skipping email.')
        logger.debug(kudos_transfer.network)
        logger.debug(settings.ENABLE_NOTIFICATIONS_ON_NETWORK)
        return False

    if not kudos_transfer or not kudos_transfer.txid or not kudos_transfer.amount or not kudos_transfer.kudos_token_cloned_from:
        logger.warning('Some kudos information not found.  Skipping email.')
        return False

    # 2. Generate subject
    from_name = 'Someone' if not kudos_transfer.from_username else f'{kudos_transfer.from_username}'
    on_network = '' if kudos_transfer.network == 'mainnet' else f'({kudos_transfer.network})'
    subject = gettext(
        f"⚡️ {from_name} Sent You a {kudos_transfer.kudos_token_cloned_from.humanized_name} Kudos {on_network}"
    )

    logger.info(f'Emails to send to: {kudos_transfer.emails}')

    to_email = kudos_transfer.primary_email
    if to_email:
        cur_language = translation.get_language()
        try:
            setup_lang(to_email)
            # TODO:  Does the from_email field in the database mean nothing?  We just override it here.
            from_email = settings.CONTACT_EMAIL
            # 3. Render email
            html, text = render_new_kudos_email(to_email, kudos_transfer, True)

            # 4. Send email unless the email address has notifications disabled
            if not should_suppress_notification_email(to_email, 'kudos'):
                # TODO:  Should we be doing something with the response from SendGrid?
                #        Maybe we should store it somewhere.
                send_mail(from_email, to_email, subject, text, html)
        finally:
            # 5.  Do translation
            translation.activate(cur_language)

    return True
示例#8
0
文件: views.py 项目: cmditch/web
def whitepaper_new(request, ratelimited=False):

    context = {
        'active': 'whitepaper',
        'title': 'Whitepaper',
        'minihero': 'Whitepaper',
        'suppress_logo': True,
    }
    if not request.POST.get('submit', False):
        return TemplateResponse(request, 'whitepaper_new.html', context)

    if ratelimited:
        context[
            'msg'] = "You're ratelimited. Please contact [email protected]"
        return TemplateResponse(request, 'whitepaper_accesscode.html', context)

    context['role'] = request.POST.getlist('role')
    context['email'] = request.POST.get('email')
    context['comments'] = request.POST.get('comments')
    ip = get_ip(request)
    body = """
Email: {} \n
Role: {}\n
Comments: {}\n
IP: {}\n

https://gitcoin.co/_administration/tdi/whitepaperaccessrequest/

    """.format(context['email'], context['role'], context['comments'], ip)
    send_mail(settings.CONTACT_EMAIL, settings.CONTACT_EMAIL,
              "New Whitepaper Request", str(body))

    war = WhitepaperAccessRequest.objects.create(
        email=context['email'],
        role=context['role'],
        comments=context['comments'],
        ip=ip,
    )

    valid_email = True
    try:
        validate_email(request.POST.get('email', False))
    except Exception as e:
        valid_email = False

    if not request.POST.get('email', False) or not valid_email:
        context['msg'] = "Invalid Email. Please contact [email protected]"
        return TemplateResponse(request, 'whitepaper_new.html', context)

    context['msg'] = "Your request has been sent."
    return TemplateResponse(request, 'whitepaper_new.html', context)
示例#9
0
def send_personal_token_created(profile, ptoken):
    from_email = settings.CONTACT_EMAIL
    to_email = profile.email
    cur_language = translation.get_language()

    try:
        setup_lang(to_email)
        html, text, subject = render_ptoken_created(ptoken)

        if not should_suppress_notification_email(to_email,
                                                  'personal_token_created'):
            send_mail(from_email,
                      to_email,
                      subject,
                      text,
                      html,
                      categories=['transactional',
                                  func_name()])
    finally:
        translation.activate(cur_language)
示例#10
0
文件: views.py 项目: theassyrian/web
def process_accesscode_request(request, pk):

    obj = WhitepaperAccessRequest.objects.get(pk=pk)
    context = {
        'obj': obj,
    }

    if obj.processed:
        raise

    if request.POST.get('submit', False):
        h = hashlib.new('ripemd160')
        h.update(h.hexdigest() + str(timezone.now()))
        invitecode = h.hexdigest()[:29]

        code = AccessCodes.objects.create(
            invitecode=invitecode,
            maxuses=1,
        )
        obj.processed = True
        obj.save()

        from_email = settings.PERSONAL_CONTACT_EMAIL
        to_email = obj.email
        subject = request.POST.get('subject')
        body = request.POST.get('body').replace('[code]', invitecode)
        send_mail(from_email,
                  to_email,
                  subject,
                  body,
                  from_name="Kevin from Gitcoin.co")
        messages.success(request, 'Invite sent')

        return redirect(
            '/_administration/tdi/whitepaperaccessrequest/?processed=False')

    return TemplateResponse(request, 'process_accesscode_request.html',
                            context)
示例#11
0
def whitepaper_access(request, ratelimited=False):

    context = {
        'active': 'whitepaper',
        'title': _('Whitepaper'),
        'minihero': _('Whitepaper'),
        'suppress_logo': True,
    }
    if not request.POST.get('submit', False):
        return TemplateResponse(request, 'whitepaper_accesscode.html', context)

    if ratelimited:
        context['msg'] = _(
            "You're ratelimited. Please contact [email protected]")
        return TemplateResponse(request, 'whitepaper_accesscode.html', context)

    context['accesskey'] = request.POST.get('accesskey')
    context['email'] = request.POST.get('email')
    access_codes = AccessCodes.objects.filter(
        invitecode=request.POST.get('accesskey'))
    valid_access_code = access_codes.exists()
    if not valid_access_code:
        context['msg'] = _(
            "Invalid Access Code. Please contact [email protected]")
        return TemplateResponse(request, 'whitepaper_accesscode.html', context)

    ac = access_codes.first()
    if ac.uses >= ac.maxuses:
        context['msg'] = _(
            "You have exceeded your maximum number of uses for this access code. Please contact [email protected]"
        )
        return TemplateResponse(request, 'whitepaper_accesscode.html', context)

    valid_email = True
    try:
        validate_email(request.POST.get('email', False))
    except Exception as e:
        valid_email = False

    if not request.POST.get('email', False) or not valid_email:
        context['msg'] = _("Invalid Email. Please contact [email protected]")
        return TemplateResponse(request, 'whitepaper_accesscode.html', context)

    ip = get_ip(request)

    wa = WhitepaperAccess.objects.create(
        invitecode=request.POST.get('accesskey', False),
        email=request.POST.get('email', False),
        ip=ip,
    )

    send_mail(
        settings.CONTACT_EMAIL,
        settings.CONTACT_EMAIL,
        _("New Whitepaper Generated"),
        str(wa),
        categories=['admin', 'whitepaper_gen'],
    )

    # bottom watermark
    packet1 = BytesIO()
    can = canvas.Canvas(packet1, pagesize=letter)

    grey = Color(22 / 255, 6 / 255, 62 / 255, alpha=0.3)
    can.setFillColor(grey)
    can.setFontSize(8)
    lim = 30
    email__etc = wa.email if len(wa.email) < lim else wa.email[0:lim] + "..."
    msg = gettext(
        "Generated for access code {} by email {} at {} via ip: {}. https://gitcoin.co/whitepaper"
    ).format(wa.invitecode, email__etc,
             wa.created_on.strftime("%Y-%m-%d %H:%M"), wa.ip)
    charlength = 3.5
    width = len(msg) * charlength
    left = (600 - width) / 2
    can.drawString(left, 7, msg)
    can.save()

    # middle watermark
    packet2 = BytesIO()
    can = canvas.Canvas(packet2, pagesize=letter)
    grey = Color(22 / 255, 6 / 255, 62 / 255, alpha=0.02)
    can.setFillColor(grey)
    can.setFontSize(100)
    msg = "WP{}".format(str(wa.pk).zfill(5))
    charlength = 55
    width = len(msg) * charlength
    left = (600 - width) / 2
    can.rotate(45)
    can.drawString(320, 50, msg)
    can.save()

    # move to the beginning of the StringIO buffer
    path_to_file = 'assets/other/wp.pdf'
    new_pdf1 = PdfFileReader(packet1)
    new_pdf2 = PdfFileReader(packet2)
    # read your existing PDF

    existing_pdf = PdfFileReader(open(path_to_file, "rb"))
    output = PdfFileWriter()
    # add the "watermark" (which is the new pdf) on the existing page
    try:
        for i in range(0, 50):
            page = existing_pdf.getPage(i)
            page.mergePage(new_pdf1.getPage(0))
            if i != 0:
                page.mergePage(new_pdf2.getPage(0))
            output.addPage(page)
    except Exception as e:
        print(e)
    # finally, write "output" to a real file
    outputfile = "output/whitepaper_{}.pdf".format(wa.pk)
    outputStream = open(outputfile, "wb")
    output.write(outputStream)
    outputStream.close()

    filename = outputfile
    wrapper = FileWrapper(open(filename, 'rb'))

    response = HttpResponse(wrapper, content_type='application/pdf')
    response[
        'Content-Disposition'] = 'attachment; filename="GitcoinWhitepaper.pdf"'
    response['Content-Length'] = os.path.getsize(filename)
    return response
示例#12
0
    def handle(self, *args, **options):
        bounties = Bounty.objects.prefetch_related('fulfillments').filter(
            network='mainnet',
            current_bounty=True,
            web3_created__gte=options['start_date'],
            web3_created__lte=options['end_date']).order_by(
                'web3_created', 'id')
        formatted_bounties = imap(self.format_bounty, bounties)

        frs = FaucetRequest.objects.filter(
            created_on__gte=options['start_date'],
            created_on__lte=options['end_date'],
            fulfilled=True,
        ).order_by('created_on', 'id')
        formatted_frs = imap(self.format_faucet_distribution, frs)

        tips = Tip.objects.filter(network='mainnet',
                                  created_on__gte=options['start_date'],
                                  created_on__lte=options['end_date']).exclude(
                                      txid='', ).order_by('created_on', 'id')
        formatted_tips = imap(self.format_tip, tips)

        enssubregistrations = ENSSubdomainRegistration.objects.filter(
            created_on__gte=options['start_date'],
            created_on__lte=options['end_date']).order_by('created_on', 'id')
        formted_enssubreg = imap(self.format_ens_reg, enssubregistrations)

        # python3 list hack
        formatted_frs = [x for x in formatted_frs]
        formatted_bounties = [x for x in formatted_bounties]
        formatted_tips = [x for x in formatted_tips]
        formateted_enssubregistrations = [x for x in formted_enssubreg]
        all_items = formatted_bounties + formatted_tips + formatted_frs + formateted_enssubregistrations

        csvfile = StringIO()
        csvwriter = csv.DictWriter(
            csvfile,
            fieldnames=[
                'type', 'created_on', 'last_activity', 'amount',
                'denomination', 'amount_eth', 'amount_usdt', 'from_address',
                'claimee_address', 'repo', 'from_username',
                'fulfiller_github_username', 'status', 'comments', 'payee_bio',
                'payee_location'
            ])
        csvwriter.writeheader()

        items = sorted(all_items, key=lambda x: x['created_on'])
        has_rows = False
        for item in items:
            has_rows = True
            csvwriter.writerow(item)

        start = options['start_date'].strftime(DATE_FORMAT_HYPHENATED)
        end = options['end_date'].strftime(DATE_FORMAT_HYPHENATED)
        now = str(datetime.datetime.now())
        if has_rows:
            subject = 'Gitcoin Activity report from %s to %s' % (start, end)

            url = self.upload_to_s3(
                'activity_report_%s_%s_generated_on_%s.csv' %
                (start, end, now), csvfile.getvalue())
            body = '<a href="%s">%s</a>' % (url, url)
            print(url)

            send_mail(settings.CONTACT_EMAIL,
                      settings.CONTACT_EMAIL,
                      subject,
                      body='',
                      html=body)

            self.stdout.write(
                self.style.SUCCESS('Sent activity report from %s to %s to %s' %
                                   (start, end, settings.CONTACT_EMAIL)))
        else:
            self.stdout.write(
                self.style.WARNING('No activity from %s to %s to report' %
                                   (start, end)))
示例#13
0
def redeem_bulk_kudos(self,
                      kt_id,
                      delay_if_gas_prices_gt_redeem=50,
                      override_gas_price=None,
                      send_notif_email=False,
                      override_lock_timeout=LOCK_TIMEOUT,
                      retry=False):
    """
    :param self:
    :param kt_id:
    :return:
    """
    try:
        if True:  # override for allowing many xdai minting; we can change this back later there is a race condition
            # but for now the lock was providing more trouble than good - KO 10/20/2020
            #with redis.lock("tasks:redeem_bulk_kudos:%s" % kt_id, timeout=override_lock_timeout):
            multiplier = 1
            # high gas prices, 5 hour gas limit - DL
            gas_price = int(
                float(recommend_min_gas_price_to_confirm_in_time(300)) *
                multiplier)
            if override_gas_price:
                gas_price = override_gas_price
            if gas_price > delay_if_gas_prices_gt_redeem:
                # do not retry is gas prices are too high
                # TODO: revisit this when gas prices go down
                # self.retry(countdown=60*10)
                return

            if override_gas_price:
                gas_price = override_gas_price * 10**9
            obj = KudosTransfer.objects.get(pk=kt_id)
            w3 = get_web3(obj.network)
            token = obj.kudos_token_cloned_from
            if token.owner_address.lower(
            ) != '0x6239FF1040E412491557a7a02b2CBcC5aE85dc8F'.lower():
                raise Exception(
                    "kudos isnt owned by Gitcoin; cowardly refusing to spend Gitcoin's ETH minting it"
                )
            kudos_owner_address = settings.KUDOS_OWNER_ACCOUNT
            kudos_owner_address = Web3.toChecksumAddress(kudos_owner_address)
            contract_addr = settings.KUDOS_CONTRACT_MAINNET
            if obj.network == 'xdai':
                contract_addr = settings.KUDOS_CONTRACT_XDAI
            if obj.network == 'rinkeby':
                contract_addr = settings.KUDOS_CONTRACT_RINKEBY
            kudos_contract_address = Web3.toChecksumAddress(contract_addr)
            contract = w3.eth.contract(
                Web3.toChecksumAddress(kudos_contract_address),
                abi=kudos_abi())
            nonce = w3.eth.getTransactionCount(kudos_owner_address)
            tx = contract.functions.clone(
                Web3.toChecksumAddress(obj.receive_address), token.token_id,
                1).buildTransaction({
                    'nonce':
                    nonce,
                    'gas':
                    500000,
                    'gasPrice':
                    gas_price,
                    'value':
                    int(token.price_finney / 1000.0 * 10**18),
                })
            private_key = settings.KUDOS_PRIVATE_KEY
            signed = w3.eth.account.signTransaction(tx, private_key)
            obj.txid = w3.eth.sendRawTransaction(signed.rawTransaction).hex()
            obj.receive_txid = obj.txid
            obj.save()
            while not has_tx_mined(obj.txid, obj.network):
                time.sleep(1)
            pass
            if send_notif_email:
                from_email = '*****@*****.**'
                from_name = 'Kevin @ Gitcoin'
                _to_email = obj.recipient_profile.email
                subject = f"Your '{obj.kudos_token_cloned_from.name}' Kudos has been minted 🌈"
                block_url = f'https://etherscan.io/tx/{obj.txid}'
                if obj.network == 'xdai':
                    block_url = f'https://blockscout.com/poa/xdai/tx/{obj.txid}/internal-transactions'
                body = f'''
Hello @{obj.recipient_profile.handle},

Back on {obj.created_on} you minted a '{obj.kudos_token_cloned_from.name}' Kudos, but the Ethereum network's gas fees were too high for us to mint it on-chain.

We're writing with good news.  The gas prices on Ethereum have come down, and we are have now minted your token.  You can now see the Kudos in your gitcoin profile ( https://gitcoin.co/{obj.recipient_profile.handle} ) or any blockchain wallet that connects to the {obj.network} network ( {block_url} ).  HOORAY!

Party on,
Kevin + the Gitcoin team
                '''
                send_mail(from_email,
                          _to_email,
                          subject,
                          body,
                          from_name=from_name)
    except (SoftTimeLimitExceeded, TimeLimitExceeded):
        print('max timeout for bulk kudos redeem exceeded ... giving up!')
    except Exception as e:
        print(e)
        if self.request.retries < self.max_retries:
            self.retry(countdown=(30 * (self.request.retries + 1)))
        else:
            print("max retries for bulk kudos redeem exceeded ... giving up!")
示例#14
0
def export_search_to_csv(self, body, user_handle, retry:bool = True) -> None:


    CSV_HEADER = [
        'profile_id',
        'join_date',
        'github_created_at',
        'first_name',
        'last_name',
        'email',
        'handle',
        'sms_verification',
        'persona',
        'rank_coder',
        'rank_funder',
        'num_hacks_joined',
        'which_hacks_joined',
        'hack_work_starts',
        'hack_work_submits',
        'hack_work_start_orgs',
        'hack_work_submit_orgs',
        'bounty_work_starts',
        'bounty_work_submits',
        'hack_started_feature',
        'hack_started_code_review',
        'hack_started_security',
        'hack_started_design',
        'hack_started_documentation',
        'hack_started_bug',
        'hack_started_other',
        'hack_started_improvement',
        'started_feature',
        'started_code_review',
        'started_security',
        'started_design',
        'started_documentation',
        'started_bug',
        'started_other',
        'started_improvement',
        'submitted_feature',
        'submitted_code_review',
        'submitted_security',
        'submitted_design',
        'submitted_documentation',
        'submitted_bug',
        'submitted_other',
        'submitted_improvement',
        'bounty_earnings',
        'bounty_work_start_orgs',
        'bounty_work_submit_orgs',
        'kudos_sends',
        'kudos_receives',
        'hack_winner_kudos_received',
        'grants_opened',
        'grant_contributed',
        'grant_contributions',
        'grant_contribution_amount',
        'num_actions',
        'action_points',
        'avg_points_per_action',
        'last_action_on',
        'keywords',
        'activity_level',
        'reliability',
        'average_rating',
        'longest_streak',
        'earnings_count',
        'follower_count',
        'following_count',
        'num_repeated_relationships',
        'verification_status'
    ]

    user_profile = Profile.objects.get(handle=user_handle)

    PAGE_SIZE = 1000
    proxy_req = HttpRequest()
    proxy_req.method = 'GET'
    remote_url = f'{settings.HAYSTACK_ELASTIC_SEARCH_URL}/haystack/modelresult/_search'

    query_data = json.loads(body)
    proxy_request = proxy_view(proxy_req, remote_url, {'data': body})
    proxy_json_str = proxy_request.content.decode('utf-8')
    proxy_body = json.loads(proxy_json_str)
    if not proxy_body['timed_out']:
        total_hits = proxy_body['hits']['total']
        hits = proxy_body['hits']['hits']
        finished = False
        output = []
        results = []
        if total_hits < PAGE_SIZE:
            finished = True
            results = hits

        if not finished:

            max_loops = math.ceil(total_hits / PAGE_SIZE)
            for x in range(0, max_loops):
                new_body = query_data
                new_body['from'] = 0 if x is 0 else (PAGE_SIZE * x) + 1
                new_body['size'] = PAGE_SIZE
                new_body = json.dumps(new_body)
                proxy_request = proxy_view(proxy_req, remote_url, {'data': new_body})
                proxy_json_str = proxy_request.content.decode('utf-8')
                proxy_body = json.loads(proxy_json_str)
                hits = proxy_body['hits']['hits']
                results = results + hits

        for result in results:
            source = result['_source']
            row_item = {}
            for k in source.copy():

                new_column = k.replace('_exact', '')

                if new_column in CSV_HEADER:
                    row_item[new_column] = source[k]
            output.append(row_item)
        now = datetime.now()
        csv_file_path = f'/tmp/user-directory-export-{user_profile.handle}-{now}.csv'
        try:
            with open(csv_file_path, 'w', encoding='utf-8') as csvfile:
                writer = csv.DictWriter(csvfile, fieldnames=CSV_HEADER)
                writer.writeheader()
                writer.writerows(output)
        except IOError:
            print("I/O error")
        if os.path.isfile(csv_file_path):

            to_email = user_profile.user.email
            from_email = settings.CONTACT_EMAIL

            subject = "Your exported user directory csv is attached"
            html = text = f'Your exported {csv_file_path.replace("/tmp/", "")} is attached.'
            send_mail(
                from_email,
                to_email,
                subject,
                text,
                html,
                from_name=f"@{user_profile.handle}",
                categories=['transactional'],
                csv=csv_file_path
            )
示例#15
0
    def handle(self, *args, **options):
        bounties = Bounty.objects.prefetch_related('fulfillments').current().filter(
            network='mainnet',
            web3_created__gte=options['start_date'],
            web3_created__lte=options['end_date']
        ).order_by('web3_created', 'id')
        formatted_bounties = imap(self.format_bounty, bounties)

        frs = FaucetRequest.objects.filter(
            created_on__gte=options['start_date'],
            created_on__lte=options['end_date'],
            fulfilled=True,
        ).order_by('created_on', 'id')
        formatted_frs = imap(self.format_faucet_distribution, frs)

        all_scram = []
        for _class in all_sendcryptoasset_models():
            objs = _class.objects.filter(
                network='mainnet',
                created_on__gte=options['start_date'],
                created_on__lte=options['end_date']
            ).send_success().order_by('created_on', 'id')
            objs = imap(self.format_cryptoasset, objs)
            objs = [x for x in objs]
            all_scram += objs

        enssubregistrations = ENSSubdomainRegistration.objects.filter(
            created_on__gte=options['start_date'],
            created_on__lte=options['end_date']
        ).order_by('created_on', 'id')
        formted_enssubreg = imap(self.format_ens_reg, enssubregistrations)

        # python3 list hack
        formatted_frs = [x for x in formatted_frs]
        formatted_bounties = [x for x in formatted_bounties]
        formateted_enssubregistrations = [x for x in formted_enssubreg]
        all_items = formatted_bounties + all_scram + formatted_frs + formateted_enssubregistrations

        csvfile = StringIO()
        csvwriter = csv.DictWriter(csvfile, fieldnames=[
            'type', 'created_on', 'last_activity', 'amount', 'denomination', 'amount_eth',
            'amount_usdt', 'from_address', 'claimee_address', 'repo', 'from_username',
            'fulfiller_github_username', 'status', 'comments', 'payee_bio', 'payee_location'])
        csvwriter.writeheader()

        items = sorted(all_items, key=lambda x: x['created_on'])
        has_rows = False
        for item in items:
            has_rows = True
            csvwriter.writerow(item)

        start = options['start_date'].strftime(DATE_FORMAT_HYPHENATED)
        end = options['end_date'].strftime(DATE_FORMAT_HYPHENATED)
        now = str(datetime.datetime.now())
        if has_rows:
            subject = f'Gitcoin Activity report from {start} to {end}'

            url = self.upload_to_s3(f'activity_report_{start}_{end}_generated_on_{now}.csv', csvfile.getvalue())
            body = f'<a href="{url}">{url}</a>'
            print(url)

            send_mail(
                settings.CONTACT_EMAIL,
                settings.CONTACT_EMAIL,
                subject,
                body='',
                html=body,
                categories=['admin', 'activity_report'],
            )

            self.stdout.write(
                self.style.SUCCESS('Sent activity report from %s to %s to %s' % (start, end, settings.CONTACT_EMAIL))
            )
        else:
            self.stdout.write(self.style.WARNING('No activity from %s to %s to report' % (start, end)))