Example #1
0
def _list(client):
    """ Lists all of the apps that the user has rated

    If no apps have been rated, then an empty formatted list is printed

    Args:
        client (two1.server.rest_client.TwentyOneRestClient) an object for
            sending authenticated requests to the TwentyOne backend.

    Raises:
        ServerRequestError: If server error occurs other than a 404
    """
    logger.info(uxstring.UxString.rating_list)

    try:
        ratings = client.get_ratings()
        headers = ["id", "App title", "Creator", "Rating", "Rating Date"]
        ratings = ratings.json()["ratings"]
        rows = []
        for rating in ratings:
            rating_date = util.format_date(rating["rating_date"])
            rating_score = "{}/5".format(rating["rating"])
            rows.append([rating["app_id"], rating["app_title"], rating["app_creator"],
                         rating_score, rating_date])

        logger.info(tabulate(rows, headers, tablefmt="simple"))

    except exceptions.ServerRequestError as e:
        if e.status_code == 404:
            logger.info(uxstring.UxString.no_ratings)
            return
        else:
            raise e
Example #2
0
def buy_bitcoin(client, amount):
    if click.confirm(uxstring.UxString.buybitcoin_confirmation_prompt):
        logger.info(uxstring.UxString.coinbase_purchase_in_progress)
        try:
            resp = client.buy_bitcoin_from_exchange(amount, "satoshis", commit=True)
        except exceptions.ServerRequestError as e:
            if e.status_code == 403 and e.data.get("error") == "TO703":
                logger.error(uxstring.UxString.coinbase_max_buy_reached)
                return
            elif e.status_code == 422:
                logger.error(e.data.get("message"))

        buy_result = resp.json()
        if buy_result["status"] == "canceled":
            logger.info(uxstring.UxString.buybitcoin_error.format(
                click.style("Buy was canceled.", bold=True, fg="red")))

            return buy_result

        amount_bought = int(float(buy_result["amount"]["amount"]) * 1e8)
        btc_bought = "{} {}".format(amount_bought, 'satoshis')

        dollars_paid = "{} {}".format(buy_result["total"]["amount"],
                                      buy_result["total"]["currency"])

        logger.info(uxstring.UxString.buybitcoin_success.format(btc_bought, dollars_paid))

        if "instant" in buy_result and buy_result["instant"]:
            logger.info(uxstring.UxString.buybitcoin_success_instant)
        elif "payout_at" in buy_result:
            payout_time = util.format_date(buy_result["payout_at"])

            logger.info(uxstring.UxString.buybitcoin_success_payout_time.format(payout_time))
    else:
        logger.info("\nPurchase canceled", fg="magenta")
Example #3
0
def buy_bitcoin(client, amount):
    if click.confirm(uxstring.UxString.buybitcoin_confirmation_prompt):
        logger.info(uxstring.UxString.coinbase_purchase_in_progress)
        try:
            resp = client.buy_bitcoin_from_exchange(amount,
                                                    "satoshis",
                                                    commit=True)
        except exceptions.ServerRequestError as e:
            PHOTO_ID_ERROR = "Before you will be able to complete this buy, "\
                "you must provide additional information at "\
                "https://www.coinbase.com/photo-id"
            USERNAME_ERROR = "To process payments we require a valid user name. "\
                "Please go to settings to update your information."
            if e.status_code == 403 and e.data.get("error") == "TO703":
                logger.error(uxstring.UxString.coinbase_max_buy_reached)
                return
            elif e.status_code == 500 and e.data.get(
                    "error") == PHOTO_ID_ERROR:
                logger.error(uxstring.UxString.coinbase_needs_photo_id)
                return
            elif e.status_code == 500 and e.data.get(
                    "error") == USERNAME_ERROR:
                logger.error(uxstring.UxString.coinbase_needs_username)
                return

        buy_result = resp.json()
        if buy_result["status"] == "canceled":
            logger.info(
                uxstring.UxString.buybitcoin_error.format(
                    click.style("Buy was canceled.", bold=True, fg="red")))

            return buy_result

        amount_bought = int(float(buy_result["amount"]["amount"]) * 1e8)
        btc_bought = "{} {}".format(amount_bought, 'satoshis')

        dollars_paid = "{} {}".format(buy_result["total"]["amount"],
                                      buy_result["total"]["currency"])

        logger.info(
            uxstring.UxString.buybitcoin_success.format(
                btc_bought, dollars_paid))

        if "instant" in buy_result and buy_result["instant"]:
            logger.info(uxstring.UxString.buybitcoin_success_instant)
        elif "payout_at" in buy_result:
            payout_time = util.format_date(buy_result["payout_at"])

            logger.info(
                uxstring.UxString.buybitcoin_success_payout_time.format(
                    payout_time))
    else:
        logger.info("\nPurchase canceled", fg="magenta")
Example #4
0
def buybitcoin_history(config, client, exchange):
    resp = client.get_coinbase_status()
    if not resp.ok:
        raise exceptions.Two1Error("Failed to get exchange status")

    coinbase = resp.json()["coinbase"]

    if not coinbase:
        # Not linked, prompt user to info
        return buybitcoin_config(config, client, exchange)
    else:
        resp = client.get_coinbase_history()
        history = resp.json()["history"]

        lines = [uxstring.UxString.coinbase_history_title]

        for entry in history:
            amount = entry["amount"]
            deposit_status = entry["deposit_status"]
            payout_time = util.format_date(entry["payout_time"])
            payout_address = entry["payout_address"]

            description = "N/A"
            if deposit_status == "COMPLETED":
                description = uxstring.UxString.coinbase_wallet_completed.format(
                    payout_time)
            else:
                description = uxstring.UxString.coinbase_wallet_pending.format(
                    payout_time)

            created = util.format_date(entry["created"])
            lines.append(
                uxstring.UxString.coinbase_history.format(
                    created, amount, payout_address, description))

        if len(history) == 0:
            lines.append(uxstring.UxString.coinbase_no_bitcoins_purchased)

        prints = "\n\n".join(lines)
        logger.info(prints, pager=True)
Example #5
0
def history(ctx, n, reverse, json_output, account):
    """ Print the wallet's history
    """
    w = ctx.obj['wallet']
    history = w.transaction_history(accounts=list(account))

    if reverse:
        h = list(reversed(history))
    else:
        h = history

    if n > 0:
        h = h[:n]

    if json_output:
        click.echo(json.dumps(h))
        return

    for i, th in enumerate(h):
        dt = util.format_date(int(th['time']))

        click.echo("%s (%s)" % (th['txid'], dt))
        click.echo("%s" % ('-' * 86))
        click.echo("Type: %s" % (th['classification']))
        if th['classification'] == "deposit":
            for d in th['deposits']:
                click.echo("Received %d satoshis into %s (Account: %s)" % (
                    d['value'], d['address'], d['acct']))
        elif th['classification'] in ["spend", "internal_transfer"]:
            for i in range(max(len(th['spends']), len(th['deposits'])) + 1):
                msg = ""
                if i < len(th['spends']):
                    s = th['spends'][i]
                    msg = "%12d satoshis from %35s" % (s['value'], s['address'])
                else:
                    msg = "%s" % (" " * 62)
                if i < len(th['deposits']):
                    d = th['deposits'][i]
                    msg += "%s%12d satoshis to %35s (%s)" % (
                        " " * 5,
                        d['value'],
                        d['address'],
                        d['addr_type'])
                if i == len(th['deposits']):
                    msg += "%s%12d satoshis to %35s (fees)" % (
                        " " * 5,
                        th['fees'],
                        "miner")

                click.echo(msg)

        click.echo()
Example #6
0
def get_search_results(config, client, page):
    """ Queries the marketplace for published apps

    Args:
        config (Config): config object used for getting .two1 information
        client (TwentyOneRestClient): rest client used for communication with the backend api.
        page (int): the page number used in querying the paginated marketplace api.

    Returns:
        int: the total number of pages returned by the server
    """
    resp = client.get_published_apps(config.username, page)
    resp_json = resp.json()
    search_results = resp_json["results"]
    if search_results is None or len(search_results) == 0:
        logger.info(click.style(
            "You haven't published any apps to the marketplace yet. Use ",
            fg="blue") +
                    click.style("21 publish submit {PATH_TO_MANIFEST_FILE}",
                                bold=True,
                                fg="blue") +
                    click.style(" to publish your apps to the marketplace.",
                                fg="blue"),
                    fg="blue")
        return 0

    total_pages = resp_json["total_pages"]
    logger.info("\nPage {}/{}".format(page + 1, total_pages), fg="green")
    headers = [
        "id", "Title", "Url", "Rating", "Is up", "Is healthy",
        "Average Uptime", "Last Update"
    ]
    rows = []
    for r in search_results:
        rating = "Not yet Rated"
        if r["rating_count"] > 0:
            rating = "{:.1f} ({} rating".format(r["average_rating"],
                                                int(r["rating_count"]))
            if r["rating_count"] > 1:
                rating += "s"
            rating += ")"
        rows.append([
            r["id"], r["title"], r["app_url"], rating,
            str(r["is_up"]),
            str(r["is_healthy"]), "{:.2f}%".format(r["average_uptime"] * 100),
            util.format_date(r["last_update"])
        ])

    logger.info(tabulate(rows, headers, tablefmt="simple"))

    return total_pages
Example #7
0
def _get_headline(entry):
    # headline
    local_date = util.format_date(entry["date"])

    if entry["amount"] > 0:
        headline = uxstring.UxString.debit_message.format(local_date, entry["amount"])
    elif entry["reason"] == "flush_payout" or entry["reason"] == "earning_payout":
        headline = uxstring.UxString.blockchain_credit_message.format(local_date, entry["amount"],
                                                                      -entry["amount"])
    else:
        headline = uxstring.UxString.credit_message.format(local_date, entry["amount"])

    headline = click.style(headline, fg="cyan")
    return headline
Example #8
0
def _get_headline(entry):
    # headline
    local_date = util.format_date(entry["date"])

    if entry["amount"] > 0:
        headline = uxstring.UxString.debit_message.format(local_date, entry["amount"])
    elif entry["reason"] == "flush_payout" or entry["reason"] == "earning_payout":
        headline = uxstring.UxString.blockchain_credit_message.format(local_date, entry["amount"],
                                                                      -entry["amount"])
    else:
        headline = uxstring.UxString.credit_message.format(local_date, entry["amount"])

    headline = click.style(headline, fg="cyan")
    return headline
Example #9
0
def buybitcoin_history(config, client, exchange):
    resp = client.get_coinbase_status()
    if not resp.ok:
        raise exceptions.Two1Error("Failed to get exchange status")

    coinbase = resp.json()["coinbase"]

    if not coinbase:
        # Not linked, prompt user to info
        return buybitcoin_config(config, client, exchange)
    else:
        resp = client.get_coinbase_history()
        history = resp.json()["history"]

        lines = [uxstring.UxString.coinbase_history_title]

        for entry in history:
            amount = entry["amount"]
            deposit_status = entry["deposit_status"]
            payout_time = util.format_date(entry["payout_time"])
            payout_address = entry["payout_address"]

            description = "N/A"
            if deposit_status == "COMPLETED":
                description = uxstring.UxString.coinbase_wallet_completed.format(payout_time)
            else:
                description = uxstring.UxString.coinbase_wallet_pending.format(payout_time)

            created = util.format_date(entry["created"])
            lines.append(uxstring.UxString.coinbase_history.format(
                created, amount, payout_address, description))

        if len(history) == 0:
            lines.append(uxstring.UxString.coinbase_no_bitcoins_purchased)

        prints = "\n\n".join(lines)
        logger.info(prints, pager=True)
Example #10
0
def create_notification_line(msg):
    """Create a formatted notification line from a message dict.

    Args:
        msg (dict): a raw inbox notification in dict format

    Returns:
        str: a formatted notification message
    """
    local_time = util.format_date(msg["time"])
    message_line = click.style("{} : {} from {}\n".format(local_time, msg["type"],
                                                          msg["from"]),
                               fg="cyan")
    message_line += "{}\n".format(msg["content"])
    return message_line
Example #11
0
def history(ctx, n, reverse, json_output, account):
    """ Print the wallet's history
    """
    w = ctx.obj['wallet']
    history = w.transaction_history(accounts=list(account))

    if reverse:
        h = list(reversed(history))
    else:
        h = history

    if n > 0:
        h = h[:n]

    if json_output:
        click.echo(json.dumps(h))
        return

    for i, th in enumerate(h):
        dt = util.format_date(int(th['time']))

        click.echo("%s (%s)" % (th['txid'], dt))
        click.echo("%s" % ('-' * 86))
        click.echo("Type: %s" % (th['classification']))
        if th['classification'] == "deposit":
            for d in th['deposits']:
                click.echo("Received %d satoshis into %s (Account: %s)" %
                           (d['value'], d['address'], d['acct']))
        elif th['classification'] in ["spend", "internal_transfer"]:
            for i in range(max(len(th['spends']), len(th['deposits'])) + 1):
                msg = ""
                if i < len(th['spends']):
                    s = th['spends'][i]
                    msg = "%12d satoshis from %35s" % (s['value'],
                                                       s['address'])
                else:
                    msg = "%s" % (" " * 62)
                if i < len(th['deposits']):
                    d = th['deposits'][i]
                    msg += "%s%12d satoshis to %35s (%s)" % (
                        " " * 5, d['value'], d['address'], d['addr_type'])
                if i == len(th['deposits']):
                    msg += "%s%12d satoshis to %35s (fees)" % (
                        " " * 5, th['fees'], "miner")

                click.echo(msg)

        click.echo()
def get_search_results(config, client, page):
    """ Queries the marketplace for published apps

    Args:
        config (Config): config object used for getting .two1 information
        client (TwentyOneRestClient): rest client used for communication with the backend api.
        page (int): the page number used in querying the paginated marketplace api.

    Returns:
        int: the total number of pages returned by the server
    """
    resp = client.get_published_apps(config.username, page)
    resp_json = resp.json()
    search_results = resp_json["results"]
    if search_results is None or len(search_results) == 0:
        logger.info(
            click.style("You haven't published any apps to the marketplace yet. Use ", fg="blue") +
            click.style("21 publish submit {PATH_TO_MANIFEST_FILE}", bold=True, fg="blue") +
            click.style(" to publish your apps to the marketplace.", fg="blue"), fg="blue")
        return 0

    total_pages = resp_json["total_pages"]
    logger.info("\nPage {}/{}".format(page + 1, total_pages), fg="green")
    headers = ["id", "Title", "Url", "Rating", "Is up", "Is healthy", "Average Uptime",
               "Last Update"]
    rows = []
    for r in search_results:
        rating = "Not yet Rated"
        if r["rating_count"] > 0:
            rating = "{:.1f} ({} rating".format(r["average_rating"],
                                                int(r["rating_count"]))
            if r["rating_count"] > 1:
                rating += "s"
            rating += ")"
        rows.append([r["id"],
                     r["title"],
                     r["app_url"],
                     rating,
                     str(r["is_up"]),
                     str(r["is_healthy"]),
                     "{:.2f}%".format(r["average_uptime"] * 100),
                     util.format_date(r["last_update"])])

    logger.info(tabulate(rows, headers, tablefmt="simple"))

    return total_pages
Example #13
0
def buy_bitcoin(client, amount):
    if click.confirm(uxstring.UxString.buybitcoin_confirmation_prompt):
        logger.info(uxstring.UxString.coinbase_purchase_in_progress)
        try:
            resp = client.buy_bitcoin_from_exchange(amount, "satoshis", commit=True)
        except exceptions.ServerRequestError as e:
            PHOTO_ID_ERROR = "Before you will be able to complete this buy, "\
                "you must provide additional information at "\
                "https://www.coinbase.com/photo-id"
            USERNAME_ERROR = "To process payments we require a valid user name. "\
                "Please go to settings to update your information."
            if e.status_code == 403 and e.data.get("error") == "TO703":
                logger.error(uxstring.UxString.coinbase_max_buy_reached)
                return
            elif e.status_code == 500 and e.data.get("error") == PHOTO_ID_ERROR:
                logger.error(uxstring.UxString.coinbase_needs_photo_id)
                return
            elif e.status_code == 500 and e.data.get("error") == USERNAME_ERROR:
                logger.error(uxstring.UxString.coinbase_needs_username)
                return

        buy_result = resp.json()
        if buy_result["status"] == "canceled":
            logger.info(uxstring.UxString.buybitcoin_error.format(
                click.style("Buy was canceled.", bold=True, fg="red")))

            return buy_result

        amount_bought = int(float(buy_result["amount"]["amount"]) * 1e8)
        btc_bought = "{} {}".format(amount_bought, 'satoshis')

        dollars_paid = "{} {}".format(buy_result["total"]["amount"],
                                      buy_result["total"]["currency"])

        logger.info(uxstring.UxString.buybitcoin_success.format(btc_bought, dollars_paid))

        if "instant" in buy_result and buy_result["instant"]:
            logger.info(uxstring.UxString.buybitcoin_success_instant)
        elif "payout_at" in buy_result:
            payout_time = util.format_date(buy_result["payout_at"])

            logger.info(uxstring.UxString.buybitcoin_success_payout_time.format(payout_time))
    else:
        logger.info("\nPurchase canceled", fg="magenta")
Example #14
0
def display_search_info(client, listing_id):
    """ Given a listing id, format and print detailed information to the command line

    Args:
        client (TwentyOneRestClient): rest client used for communication with the backend api
        listing_id (str): unique marketplace listing id

    Raises:
        ServerRequestError: If server returns an error code other than a 404
    """
    try:
        resp = client.get_listing_info(listing_id)
    except exceptions.ServerRequestError as e:
        if e.status_code == 404:
            logger.info(uxstring.UxString.app_does_not_exist.format(listing_id))
            return
        else:
            raise e
    result_json = resp.json()

    title = click.style("App Name     : ", fg="blue") + click.style(
        "{}".format(result_json["title"]))
    created_by = click.style("Created By   : ", fg="blue") + click.style(
        "{}".format(result_json["username"]))

    desc = click.style("Description  : ", fg="blue") + click.style(
        "{}".format(result_json["description"]))
    price = click.style("Price Range  : ", fg="blue") + click.style(
        "{} - {} Satoshis").format(result_json["min_price"], result_json["max_price"])

    if result_json["rating_count"] == 0:
        rating_str = "Not yet rated"
    else:
        rating_str = "{:.1f} ({} rating".format(result_json["average_rating"],
                                                int(result_json["rating_count"]))
        if result_json["rating_count"] > 1:
            rating_str += "s"
        rating_str += ")"
    rating = click.style("Rating       : ", fg="blue") + click.style("{}".format(rating_str))

    doc_url = click.style("Docs URL     : ", fg="blue") + click.style(
        "{}".format(result_json["website_url"]))
    app_url = click.style("App URL      : ", fg="blue") + click.style(
        "{}".format(result_json["app_url"]))
    category = click.style("Category     : ", fg="blue") + click.style(
        "{}".format(result_json["category"]))
    version = click.style("Version      : ", fg="blue") + click.style(
        "{}".format(result_json["version"]))
    last_updated_str = util.format_date(result_json["updated"])
    last_update = click.style("Last Update  : ", fg="blue") + click.style(
        "{}".format(last_updated_str))
    quick_start = click.style("Quick Start\n\n", fg="blue") + click.style(
        result_json["quick_buy"])
    is_active = click.style("Status       : ", fg="blue")
    if result_json["is_active"] and result_json["is_up"] and result_json["is_healthy"]:
        is_active += click.style("Active")
    else:
        is_active += click.style("Inactive")

    availability = click.style("Availability : ", fg="blue") + click.style(
        "{:.2f}%".format(result_json["average_uptime"] * 100))

    usage_docs = None
    if "usage_docs" in result_json:
        usage_docs = click.style("Detailed usage\n\n", fg="blue") + click.style(
            result_json["usage_docs"])

    pager_components = [title, desc, created_by, price, rating, "\n",
                        is_active, availability, "\n",
                        doc_url, app_url, "\n",
                        category, version, last_update, "\n",
                        quick_start, "\n"]

    if usage_docs:
        pager_components.append(usage_docs + "\n")

    final_str = "\n".join(pager_components)

    logger.info(final_str, pager=True)
Example #15
0
def display_app_info(config, client, app_id):
    """ Displays info about the application selected

    Args:
        config (Config): config object used for getting .two1 information
        client (TwentyOneRestClient): rest client used for communication with the backend api

    Raises:
        ServerRequestError: if server returns an error code other than 404
    """
    try:
        resp = client.get_app_full_info(config.username, app_id)
        result = resp.json()
        app_info = result["app_info"]
        title = click.style("App Name        : ", fg="blue") + click.style(
            "{}".format(app_info["title"]))

        if app_info["rating_count"] == 0:
            rating = "Not yet rated"
        else:
            rating = "{:.1f} ({} rating".format(app_info["average_rating"],
                                                int(app_info["rating_count"]))
            if app_info["rating_count"] > 1:
                rating += "s"
            rating += ")"
        rating_row = click.style("Rating          : ", fg="blue") + click.style("{}".format(rating))
        up_status = click.style("Status          : ", fg="blue")
        if app_info["is_up"]:
            up_status += click.style("Up")
        else:
            up_status += click.style("Down")

        last_crawl_str = "Not yet crawled"
        if "last_crawl" in app_info:
            last_crawl_str = util.format_date(app_info["last_crawl"])

        last_crawl = click.style("Last Crawl Time : ", fg="blue") + click.style(
            "{}".format(last_crawl_str))
        version = click.style("Version         : ", fg="blue") + click.style(
            "{}".format(app_info["version"]))

        last_updated_str = util.format_date(app_info["updated"])
        last_update = click.style("Last Update     : ", fg="blue") + click.style(
            "{}".format(last_updated_str))

        availability = click.style("Availability    : ", fg="blue") + click.style(
            "{:.2f}%".format(app_info["average_uptime"] * 100))

        app_url = click.style("App URL         : ", fg="blue") + click.style(
            "{}".format(app_info["app_url"]))
        category = click.style("Category        : ", fg="blue") + click.style(
            "{}".format(app_info["category"]))

        desc = click.style("Description     : ", fg="blue") + click.style(
            "{}".format(app_info["description"]))
        price = click.style("Price Range     : ", fg="blue") + click.style(
            "{} - {} Satoshis").format(
                app_info["min_price"], app_info["max_price"])
        doc_url = click.style("Docs URL        : ", fg="blue") + click.style(
            "{}".format(app_info["docs_url"]))
        manifest_url = click.style("Manifest URL    : ", fg="blue") + click.style(
            "{}".format(app_info["manifest_url"]))

        quick_start = click.style("Quick Start\n\n", fg="blue") + click.style(
            app_info["quick_buy"])

        usage_docs = None
        if "usage_docs" in app_info:
            usage_docs = click.style("Detailed usage\n\n", fg="blue") + click.style(
                app_info["usage_docs"])

        page_components = [title, "\n",
                           rating_row, up_status, availability, last_crawl, last_update, version,
                           "\n",
                           desc, app_url, doc_url, manifest_url, "\n",
                           category, price, "\n", quick_start, "\n"]
        if usage_docs:
            page_components.append(usage_docs + "\n")
        final_str = "\n".join(page_components)
        logger.info(final_str, pager=True)

    except ServerRequestError as e:
        if e.status_code == 404:
            logger.info(uxstring.UxString.app_does_not_exist.format(app_id))
        else:
            raise e
Example #16
0
def display_app_info(config, client, app_id):
    """ Displays info about the application selected

    Args:
        config (Config): config object used for getting .two1 information
        client (TwentyOneRestClient): rest client used for communication with the backend api

    Raises:
        ServerRequestError: if server returns an error code other than 404
    """
    try:
        resp = client.get_app_full_info(config.username, app_id)
        result = resp.json()
        app_info = result["app_info"]
        title = click.style("App Name        : ", fg="blue") + click.style(
            "{}".format(app_info["title"]))

        if app_info["rating_count"] == 0:
            rating = "Not yet rated"
        else:
            rating = "{:.1f} ({} rating".format(app_info["average_rating"],
                                                int(app_info["rating_count"]))
            if app_info["rating_count"] > 1:
                rating += "s"
            rating += ")"
        rating_row = click.style("Rating          : ",
                                 fg="blue") + click.style("{}".format(rating))
        up_status = click.style("Status          : ", fg="blue")
        if app_info["is_up"]:
            up_status += click.style("Up")
        else:
            up_status += click.style("Down")

        last_crawl_str = "Not yet crawled"
        if "last_crawl" in app_info:
            last_crawl_str = util.format_date(app_info["last_crawl"])

        last_crawl = click.style("Last Crawl Time : ",
                                 fg="blue") + click.style(
                                     "{}".format(last_crawl_str))
        version = click.style("Version         : ", fg="blue") + click.style(
            "{}".format(app_info["version"]))

        last_updated_str = util.format_date(app_info["updated"])
        last_update = click.style("Last Update     : ",
                                  fg="blue") + click.style(
                                      "{}".format(last_updated_str))

        availability = click.style("Availability    : ",
                                   fg="blue") + click.style("{:.2f}%".format(
                                       app_info["average_uptime"] * 100))

        app_url = click.style("Public App URL  : ", fg="blue") + click.style(
            "{}".format(app_info["app_url"]))
        original_url = click.style("Private App URL : ",
                                   fg="blue") + click.style("{}".format(
                                       app_info["original_url"]))
        category = click.style("Category        : ", fg="blue") + click.style(
            "{}".format(app_info["category"]))

        desc = click.style("Description     : ", fg="blue") + click.style(
            "{}".format(app_info["description"]))
        price = click.style(
            "Price Range     : ",
            fg="blue") + click.style("{} - {} Satoshis").format(
                app_info["min_price"], app_info["max_price"])
        doc_url = click.style("Docs URL        : ", fg="blue") + click.style(
            "{}".format(app_info["docs_url"]))
        manifest_url = click.style("Manifest URL    : ",
                                   fg="blue") + click.style("{}".format(
                                       app_info["manifest_url"]))

        quick_start = click.style("Quick Start\n\n", fg="blue") + click.style(
            app_info["quick_buy"])

        usage_docs = None
        if "usage_docs" in app_info:
            usage_docs = click.style("Detailed usage\n\n",
                                     fg="blue") + click.style(
                                         app_info["usage_docs"])

        page_components = [
            title, "\n", rating_row, up_status, availability, last_crawl,
            last_update, version, "\n", desc, app_url, original_url, doc_url,
            manifest_url, "\n", category, price, "\n", quick_start, "\n"
        ]
        if usage_docs:
            page_components.append(usage_docs + "\n")
        final_str = "\n".join(page_components)
        logger.info(final_str, pager=True)

    except ServerRequestError as e:
        if e.status_code == 404:
            logger.info(
                "The specified id for the app ({}) does not match any apps in the "
                "marketplace.".format(app_id))
        else:
            raise e
Example #17
0
def display_search_info(client, listing_id):
    """ Given a listing id, format and print detailed information to the command line

    Args:
        client (TwentyOneRestClient): rest client used for communication with the backend api
        listing_id (str): unique marketplace listing id

    Raises:
        ServerRequestError: If server returns an error code other than a 404
    """
    try:
        resp = client.get_listing_info(listing_id)
    except exceptions.ServerRequestError as e:
        if e.status_code == 404:
            logger.info(
                uxstring.UxString.app_does_not_exist.format(listing_id))
            return
        else:
            raise e
    result_json = resp.json()

    title = click.style("App Name     : ", fg="blue") + click.style(
        "{}".format(result_json["title"]))
    created_by = click.style("Created By   : ", fg="blue") + click.style(
        "{}".format(result_json["username"]))

    desc = click.style("Description  : ", fg="blue") + click.style("{}".format(
        result_json["description"]))
    price = click.style("Price Range  : ",
                        fg="blue") + click.style("{} - {} Satoshis").format(
                            result_json["min_price"], result_json["max_price"])

    if result_json["rating_count"] == 0:
        rating_str = "Not yet rated"
    else:
        rating_str = "{:.1f} ({} rating".format(
            result_json["average_rating"], int(result_json["rating_count"]))
        if result_json["rating_count"] > 1:
            rating_str += "s"
        rating_str += ")"
    rating = click.style("Rating       : ", fg="blue") + click.style(
        "{}".format(rating_str))

    doc_url = click.style("Docs URL     : ", fg="blue") + click.style(
        "{}".format(result_json["website_url"]))
    app_url = click.style("App URL      : ", fg="blue") + click.style(
        "{}".format(result_json["app_url"]))
    category = click.style("Category     : ", fg="blue") + click.style(
        "{}".format(result_json["category"]))
    version = click.style("Version      : ", fg="blue") + click.style(
        "{}".format(result_json["version"]))
    last_updated_str = util.format_date(result_json["updated"])
    last_update = click.style("Last Update  : ", fg="blue") + click.style(
        "{}".format(last_updated_str))
    quick_start = click.style("Quick Start\n\n", fg="blue") + click.style(
        result_json["quick_buy"])
    is_active = click.style("Status       : ", fg="blue")
    if result_json["is_active"] and result_json["is_up"] and result_json[
            "is_healthy"]:
        is_active += click.style("Active")
    else:
        is_active += click.style("Inactive")

    availability = click.style("Availability : ", fg="blue") + click.style(
        "{:.2f}%".format(result_json["average_uptime"] * 100))

    usage_docs = None
    if "usage_docs" in result_json:
        usage_docs = click.style("Detailed usage\n\n",
                                 fg="blue") + click.style(
                                     result_json["usage_docs"])

    pager_components = [
        title, desc, created_by, price, rating, "\n", is_active, availability,
        "\n", doc_url, app_url, "\n", category, version, last_update, "\n",
        quick_start, "\n"
    ]

    if usage_docs:
        pager_components.append(usage_docs + "\n")

    final_str = "\n".join(pager_components)

    logger.info(final_str, pager=True)