示例#1
0
def campaign_close(campaign_id):
    decimal.getcontext().rounding = decimal.ROUND_DOWN
    campaign = PushCampaign.get_or_none(id=campaign_id)
    if not campaign:
        return jsonify({'error': 'Campaign not found'}), HTTP_404_NOT_FOUND

    # временно
    # if campaign.status != 'completed':
    #     return jsonify({
    #         'error': f"Can stop only 'completed' campaign. Current status: {campaign.status}"}), HTTP_400_BAD_REQUEST

    confirm = bool(int(request.args.get('confirm', "0")))

    wallet = PushWallet.get(link_id=campaign.wallet_link_id)
    amount_left = round(Decimal(get_balance(wallet.address, bip=True) - 0.01), 4)
    return_address = get_first_transaction(wallet.address)

    if confirm:
        campaign.status = 'closed'
        campaign.save()
        if amount_left > 0:
            result = send_coins(wallet, return_address, amount_left, wait=True)
            # тут скорее всего есть баг - нужно еще виртуальные балансы обнулять
            # иначе с рассылки придет челик, проверит баланс, применит виртуальный
            # и продукт встретит его пятисоткой потому что на балансе кампании 0
            if result is not True:
                return jsonify({'error': result}), HTTP_500_INTERNAL_SERVER_ERROR

    return jsonify({
        'amount_left': float(amount_left) if amount_left >= 0 else 0,
        'return_address': return_address
    })
示例#2
0
def campaign_check(campaign_id):
    """
    swagger: swagger/sharing/campaign-check.yml
    """
    campaign = PushCampaign.get_or_none(id=campaign_id)
    if not campaign:
        return jsonify({'error': 'Campaign not found'}), HTTPStatus.NOT_FOUND
    is_paid = check_campaign_paid(campaign)
    return jsonify({'result': is_paid})
示例#3
0
def campaign_check(campaign_id):
    campaign = PushCampaign.get_or_none(id=campaign_id)
    if not campaign:
        return jsonify({'error': 'Campaign not found'}), HTTP_404_NOT_FOUND
    wallet = PushWallet.get(link_id=campaign.wallet_link_id)
    if not ensure_balance(wallet.address, campaign.cost_pip):
        return jsonify({'result': False})
    campaign.status = 'paid'
    campaign.save()
    return jsonify({'result': True})
示例#4
0
def campaign_create():
    payload = request.get_json() or {}
    sender = payload.get('sender') or None
    spreadsheet_url = payload.get('source')
    target = payload.get('target') or None
    wallet_pass = payload.get('wallet_pass') or None
    campaign_pass = payload.get('campaign_pass') or None

    if not spreadsheet_url:
        return jsonify({'error': 'Sheet url not specified'}), HTTP_400_BAD_REQUEST

    spreadsheet_or_error = get_spreadsheet(spreadsheet_url)

    if isinstance(spreadsheet_or_error, dict):
        return jsonify(spreadsheet_or_error), HTTP_400_BAD_REQUEST
    elif not isinstance(spreadsheet_or_error, Spreadsheet):
        return jsonify({'error': 'Internal API error'}), HTTP_500_INTERNAL_SERVER_ERROR

    recipients = parse_recipients(spreadsheet_or_error)
    if not recipients:
        return jsonify({'error': 'Recipient list is empty'}), HTTP_400_BAD_REQUEST

    total_cost = sum(info['amount'] for info in recipients.values())
    total_fee = 0.02 * len(recipients)
    campaign_cost = total_cost + total_fee

    campaign_wallet = generate_and_save_wallet()
    campaign = PushCampaign.create(
        wallet_link_id=campaign_wallet.link_id,
        status='open',
        cost_pip=str(to_pip(campaign_cost)),
        company=sender,
        password=campaign_pass)

    for info in recipients.values():
        balance = str(to_pip(info['amount'] + 0.01))
        wallet = generate_and_save_wallet(
            sender=sender, recipient=info['name'], password=wallet_pass,
            campaign_id=campaign.id, virtual_balance=balance)
        info['token'] = wallet.link_id

    Recipient.bulk_create([Recipient(
        email=email, campaign_id=campaign.id,
        name=info['name'], amount_pip=str(to_pip(info['amount'])),
        wallet_link_id=info['token'], target=target
    ) for email, info in recipients.items()])

    return jsonify({
        'campaign_id': campaign.id,
        'address': campaign_wallet.address,
        'deeplink': create_deeplink(campaign_wallet.address, campaign_cost),
        'total_bip': campaign_cost
    })
示例#5
0
def push_balance(link_id):
    """
    swagger: swagger/core/push-balance.yml
    """
    payload = request.get_json() or {}
    password = payload.get('password')

    wallet = PushWallet.get_or_none(link_id=link_id)
    if not wallet:
        return jsonify({'error': 'Link does not exist'}), HTTPStatus.NOT_FOUND

    if not wallet.auth(password):
        return jsonify({'error':
                        'Incorrect password'}), HTTPStatus.UNAUTHORIZED

    # зарефакторить
    virtual_balance = None if wallet.virtual_balance == '0' else wallet.virtual_balance
    if virtual_balance is not None and not wallet.seen:
        if wallet.sent_from:
            from_w = PushWallet.get(link_id=wallet.sent_from)
            result = send_coins(from_w,
                                wallet.address,
                                amount=to_bip(wallet.virtual_balance),
                                wait=False)
            if result is not True:
                return jsonify({'error':
                                result}), HTTPStatus.INTERNAL_SERVER_ERROR
            wallet.virtual_balance = '0'
            wallet.save()
        else:
            cmp = PushCampaign.get_or_none(id=wallet.campaign_id)
            cmp_wallet = PushWallet.get(link_id=cmp.wallet_link_id)
            result = send_coins(cmp_wallet,
                                wallet.address,
                                amount=to_bip(wallet.virtual_balance),
                                wait=False)
            if result is not True:
                return jsonify({'error':
                                result}), HTTPStatus.INTERNAL_SERVER_ERROR
            wallet.virtual_balance = '0'
            recipient = Recipient.get(wallet_link_id=wallet.link_id)
            recipient.linked_at = datetime.utcnow()
            recipient.save()
            wallet.save()

    if not wallet.seen:
        wallet.seen = True
        wallet.save()
    balance = get_address_balance(wallet.address, virtual=virtual_balance)
    response = {'address': wallet.address, **balance}
    return jsonify(response)
示例#6
0
def campaign_stats(campaign_id):
    """
    swagger: swagger/sharing/campaign-stats.yml
    """
    payload = request.get_json() or {}
    password = payload.get('password')
    extended = bool(int(request.args.get('extended', "0")))

    campaign = PushCampaign.get_or_none(id=campaign_id)
    if not campaign:
        return jsonify({'error': 'Campaign not found'}), HTTPStatus.NOT_FOUND
    if not campaign.auth(password):
        return jsonify({'error':
                        'Incorrect password'}), HTTPStatus.UNAUTHORIZED

    stats = get_campaign_stats(campaign, extended=extended)
    return jsonify(stats)
示例#7
0
def create_campaign(recipients,
                    sender,
                    cost,
                    campaign_pass=None,
                    wallet_pass=None,
                    target=None,
                    customization_id=None):
    campaign_pass_hash = pbkdf2_sha256.hash(
        campaign_pass) if campaign_pass is not None else None
    campaign_wallet = generate_and_save_wallet()
    campaign = PushCampaign.create(wallet_link_id=campaign_wallet.link_id,
                                   status='open',
                                   cost_pip=str(to_pip(cost)),
                                   company=sender,
                                   password_hash=campaign_pass_hash,
                                   customization_setting_id=customization_id)

    for info in recipients.values():
        balance = str(to_pip(info['amount'] + 0.01))
        wallet = generate_and_save_wallet(
            sender=sender,
            recipient=info['name'],
            password=wallet_pass,
            campaign_id=campaign.id,
            virtual_balance=balance,
            customization_setting_id=customization_id)
        info['token'] = wallet.link_id

    Recipient.bulk_create([
        Recipient(email=email,
                  campaign_id=campaign.id,
                  name=info['name'],
                  amount_pip=str(to_pip(info['amount'])),
                  wallet_link_id=info['token'],
                  target_shop=target) for email, info in recipients.items()
    ],
                          batch_size=100)
    return campaign, campaign_wallet
示例#8
0
def campaign_close(campaign_id):
    """
    swagger: swagger/sharing/campaign-close.yml
    """
    payload = request.get_json() or {}
    password = payload.get('password')
    confirm = bool(int(request.args.get('confirm', "0")))

    campaign = PushCampaign.get_or_none(id=campaign_id)
    if not campaign:
        return jsonify({'error': 'Campaign not found'}), HTTPStatus.NOT_FOUND
    if not campaign.auth(password):
        return jsonify({'error':
                        'Incorrect password'}), HTTPStatus.UNAUTHORIZED

    decimal.getcontext().rounding = decimal.ROUND_DOWN
    wallet = PushWallet.get(link_id=campaign.wallet_link_id)
    amount_left = round(Decimal(get_balance(wallet.address, bip=True) - 0.01),
                        4)
    return_address = get_first_transaction(wallet.address)

    if confirm:
        campaign.status = 'closed'
        campaign.save()
        if amount_left > 0:
            result = send_coins(wallet, return_address, amount_left, wait=True)
            # тут скорее всего есть баг - нужно еще виртуальные балансы обнулять
            # иначе с рассылки придет челик, проверит баланс, увидит виртуальный
            # и продукт встретит его пятисоткой потому что на балансе кампании 0
            if result is not True:
                return jsonify({'error':
                                result}), HTTPStatus.INTERNAL_SERVER_ERROR

    return jsonify({
        'amount_left': float(amount_left) if amount_left >= 0 else 0,
        'return_address': return_address
    })
示例#9
0
def campaign_stats(campaign_id):
    campaign = PushCampaign.get_or_none(id=campaign_id)
    password = request.args.get('password')
    if not campaign or (campaign.password is not None and campaign.password != password):
        return jsonify({'error': 'Campaign not found'}), HTTP_404_NOT_FOUND

    extended = bool(int(request.args.get('extended', "0")))
    if extended:
        sent_list = campaign.recipients \
            .select().where(Recipient.sent_at.is_null(False)) \
            .order_by(Recipient.sent_at.asc())
        return jsonify({
            'finished': campaign.status,
            'recipients': [{
                'email': r.email, 'name': r.name,
                'amount_bip': float(to_bip(r.amount_pip)),
                'sent_at': r.sent_at,
                'opened_at': r.opened_at,
                'clicked_at': r.linked_at,
                'push_id': r.wallet_link_id,
                'target': r.target
            } for r in sent_list]
        })

    stat = campaign.recipients.select(
        fn.COUNT(Recipient.created_at).alias('emails'),
        fn.COUNT(Recipient.sent_at).alias('sent'),
        fn.COUNT(Recipient.opened_at).alias('open'),
        fn.COUNT(Recipient.linked_at).alias('clicked'))
    if stat:
        stat = stat[0]
    return jsonify({
        'sent': stat.sent,
        'open': stat.open,
        'clicked': stat.clicked,
        'status': campaign.status
    })