Exemplo n.º 1
0
def do_refresh():
    """DRY helper to refresh all stale ESI specs.

    Returns:
        list of updated ESI spec versions
    """

    status, versions = do_request("{}/versions/".format(ESI))
    if status == 200:
        for version in versions:
            if version not in ESI_SPECS:
                ESI_SPECS[version] = {"timestamp": 0, "spec": {}}

    updates = {}
    for version, details in ESI_SPECS.items():
        if not details["spec"] or details["timestamp"] < time.time() + 300:
            status, spec = do_request("{}/{}/swagger.json".format(
                ESI,
                version,
            ))
            if status == 200:
                updates[version] = {"timestamp": time.time(), "spec": spec}

    ESI_SPECS.update(updates)
    return list(updates)
Exemplo n.º 2
0
def status(*_):
    """Generic ESI status."""

    now = time.time()
    if now - STATUS["timestamp"] > 60:
        code, esi_status = do_request("{}/status.json".format(ESI))
        if code == 200:
            STATUS["status"] = esi_status
        else:
            return ":fire: (failed to fetch status.json)"

    red_routes = [
        route for route in STATUS["status"] if route["status"] == "red"
    ]
    yellow_routes = [
        route for route in STATUS["status"] if route["status"] == "yellow"
    ]

    attachments = []
    if red_routes:
        attachments.append({
            "color":
            "danger",
            "fallback":
            "{} red".format(len(red_routes)),
            "text":
            "{emoji} {count} red {emoji} {details}".format(
                emoji=":fire:" * int(
                    max(
                        round(len(red_routes) / len(STATUS["status"]) * 10),
                        1,
                    )),
                count=len(red_routes),
                details=_status_str(red_routes),
            )
        })
    if yellow_routes:
        attachments.append({
            "color":
            "warning",
            "fallback":
            "{} yellow".format(len(yellow_routes)),
            "text":
            "{emoji} {count} yellow {emoji} {details}".format(
                emoji=":fire_engine:" * int(
                    max(
                        round(len(yellow_routes) / len(STATUS["status"]) * 10),
                        1,
                    )),
                count=len(yellow_routes),
                details=_status_str(yellow_routes),
            )
        })
    if not red_routes and not yellow_routes:
        attachments.append({
            "color": "good",
            "text": "ESI is fully armed and operational!"
        })

    return REPLY(content=None, attachments=attachments)
Exemplo n.º 3
0
def do_refresh(base_url):
    """DRY helper to refresh all stale ESI specs.

    Returns:
        list of updated ESI spec versions
    """

    status, versions = do_request("{}/versions/".format(base_url))
    if status == 200:
        for version in versions:
            if version not in ESI_SPECS[base_url]:
                ESI_SPECS[base_url][version] = {"timestamp": 0, "spec": {}}

    spec_urls = {}  # url: version
    for version, details in ESI_SPECS[base_url].items():
        if not details["spec"] or details["timestamp"] < time.time() + 300:
            url = "{}/{}/swagger.json".format(base_url, version)
            spec_urls[url] = version

    updates = {}
    for url, result in multi_request(spec_urls.keys()).items():
        status, spec = result
        if status == 200:
            updates[spec_urls[url]] = {"timestamp": time.time(), "spec": spec}

    ESI_SPECS[base_url].update(updates)
    return list(updates)
Exemplo n.º 4
0
def item(msg):
    """Look up a type by ID, including dogma information."""

    start = time.time()

    if not msg.args:
        return "usage: !esi {} <id>".format(msg.command)

    item_id = msg.args[0]

    try:
        int(item_id)
    except ValueError:
        return "get outta here hackerman"

    type_url = "{}/v3/universe/types/{}/".format(esi_base_url(msg), item_id)

    ret, res = do_request(type_url)

    reqs = _expand_dogma(res, *_get_dogma_urls(msg, res))

    return SNIPPET(
        content=json.dumps(res, sort_keys=True, indent=4),
        filename="{}.json".format(item_id),
        filetype="json",
        comment="Item {}: {} ({:,d} request{} in {:,.0f}ms)".format(
            item_id,
            res["name"] if ret == 200 else "Error",
            reqs + 1,
            "s" * int(reqs > 0),
            (time.time() - start) * 1000,
        ),
        title=type_url,
    )
Exemplo n.º 5
0
def request(match, *_):
    """Make an ESI GET request, if the path is known."""

    version, *req_sections = match.groupdict()["esi_path"].split("/")
    if version not in ESI_SPECS:
        req_sections.insert(0, version)
        version = "latest"

    params = ""
    if "?" in req_sections[-1]:
        if req_sections[-1].startswith("?"):
            params = req_sections.pop()
            params = params[1:]
        else:
            # qsparams passed w/out trailing slash
            final_path, params = req_sections.pop().split("?")
            req_sections.append(final_path)

    params = html.unescape(params)
    path = "/{}/".format("/".join(x for x in req_sections if x))
    if _valid_path(path, version):
        url = "{}/{}{}{}{}".format(
            ESI,
            version,
            path,
            "?" * int(params != ""),
            params,
        )
        status, res = do_request(url)
        return "{}\n{}\n```{}```".format(
            url,
            status,
            json.dumps(res, sort_keys=True, indent=4)
        )
    return "failed to find GET {} in the {} ESI spec".format(path, version)
Exemplo n.º 6
0
def server_status(datasource):
    """Generate """

    if datasource not in ("tranquility", "singularity"):
        return "Cannot request server status for `{}`".format(datasource)

    status_code, response = do_request("{}/v1/status/?datasource={}".format(
        ESI, datasource))
    server_name = datasource.capitalize()

    if status_code == 200:
        vip = response.get("vip")
        attachment = {
            "color":
            "warning" if vip else "good",
            "title":
            "{} status".format(server_name),
            "fields": [
                {
                    "title": "Players online",
                    "value": "{:,}".format(response["players"]),
                    "short": True,
                },
                {
                    "title": "Server started",
                    "value": response["start_time"],
                    "short": True,
                },
            ],
            "fallback":
            "{} status: {:,} online, started at {}{}".format(
                server_name,
                response["players"],
                response["start_time"],
                ", in VIP" * int(vip is True),
            )
        }
        if vip:
            attachment["fields"].append({"title": "In VIP mode"})

    elif status == 503:
        attachment = {
            "color": "danger",
            "title": "{} status".format(server_name),
            "text": "Offline",
            "fallback": "{} status: Offline".format(server_name),
        }
    else:
        indeterminate = (
            "Cannot determine server status. "
            "It might be offline, or experiencing connectivity issues.")
        attachment = {
            "color": "danger",
            "title": "{} status".format(server_name),
            "text": indeterminate,
            "fallback": "{} status: {}".format(server_name, indeterminate),
        }

    return REPLY(content=None, attachments=[attachment])
Exemplo n.º 7
0
def status(msg):
    """Return the current ESI health/status."""

    base_url = esi_base_url(msg)

    now = time.time()
    if now - STATUS[base_url]["timestamp"] > 60:
        code, esi_status = do_request("{}/status.json".format(base_url))
        if code == 200:
            STATUS[base_url]["status"] = esi_status
        else:
            return ":fire: (failed to fetch status.json)"

    attachments = []
    categories = [
        ("red", ":fire:", "danger"),
        ("yellow", ":fire_engine:", "warning"),
    ]
    status_json = STATUS[base_url]["status"]

    for status_color, emoji, color_value in categories:
        routes = [
            route for route in status_json if route["status"] == status_color
        ]
        if routes:
            attachments.append({
                "color":
                color_value,
                "fallback":
                "{}: {} out of {}, {:.2%}".format(
                    status_color.capitalize(),
                    len(routes),
                    len(status_json),
                    len(routes) / len(status_json),
                ),
                "text":
                "{emoji} {count} {emoji} {details}".format(
                    emoji=emoji * max(
                        min(int(round(len(routes) / len(status_json) * 10)),
                            5), 1),
                    count="{} {} (out of {}, {:.2%})".format(
                        len(routes),
                        status_color,
                        len(status_json),
                        len(routes) / len(status_json),
                    ),
                    details=_status_str(routes),
                )
            })

    if not attachments:
        attachments.append({
            "color": "good",
            "text": ":ok_hand:",
        })

    return REPLY(content=None, attachments=attachments)
Exemplo n.º 8
0
def issue(match, msg):
    """Look up ESI-issue details on GitHub."""

    code, details = do_request(
        "https://api.github.com/repos/esi/esi-issues/issues/{}".format(
            match.groupdict()["gh_issue"]))

    if code >= 400:
        return "failed to lookup details for issue {}".format(msg.command)
    return "{} ({})".format(details["html_url"], details["state"])
Exemplo n.º 9
0
def request(match, *_):
    """Make an ESI GET request, if the path is known."""

    version, *req_sections = match.groupdict()["esi_path"].split("/")
    if version not in ESI_SPECS:
        req_sections.insert(0, version)
        version = "latest"

    params = ""
    if "?" in req_sections[-1]:
        if req_sections[-1].startswith("?"):
            params = req_sections.pop()
            params = params[1:]
        else:
            # qsparams passed w/out trailing slash
            final_path, params = req_sections.pop().split("?")
            req_sections.append(final_path)

    params = html.unescape(params)
    path = "/{}/".format("/".join(x for x in req_sections if x))
    if _valid_path(path, version):
        url = "{}/{}{}{}{}".format(
            ESI,
            version,
            path,
            "?" * int(params != ""),
            params,
        )
        start = time.time()
        status, res = do_request(url)
        try:
            status = http.HTTPStatus(status)  # pylint: disable=E1120
        except ValueError:
            pass
        else:
            status = "{} {}".format(status.value, status.name)

        return SNIPPET(
            content=json.dumps(res, sort_keys=True, indent=4),
            filename="response.json",
            filetype="json",
            comment="{} ({:,.0f}ms)".format(
                status,
                (time.time() - start) * 1000,
            ),
            title=url,
        )

    return "failed to find GET {} in the {} ESI spec".format(path, version)
Exemplo n.º 10
0
def status(*_):
    """Generic ESI status."""

    now = time.time()
    if now - STATUS["timestamp"] > 60:
        code, esi_status = do_request("{}/status.json".format(ESI))
        if code == 200:
            STATUS["status"] = esi_status
        else:
            return ":fire: (failed to fetch status.json)"

    red_routes = [
        route for route in STATUS["status"] if route["status"] == "red"
    ]
    yellow_routes = [
        route for route in STATUS["status"] if route["status"] == "yellow"
    ]

    slow_route_count = len(red_routes) + len(yellow_routes)
    slow_route_ratio = slow_route_count / len(STATUS["status"])
    if slow_route_ratio > 0.3:
        return ":fire:" * round(slow_route_ratio * 10)

    status_messages = []
    if red_routes:
        status_messages.append(":fire: {} red :fire: {}".format(
            len(red_routes),
            _status_str(red_routes),
        ))
    if yellow_routes:
        status_messages.append(
            ":fire_engine: {} yellow :fire_engine: {}".format(
                len(yellow_routes),
                _status_str(yellow_routes),
            ))

    return "\n".join(status_messages) if status_messages else ":ok_hand:"
Exemplo n.º 11
0
def sisi_status(*_):
    """Display current status of Singularity, the main test server."""

    sisi = do_request("{}/dev/status/?datasource=singularity".format(ESI))[1]
    return "Singularity status: ```{}```".format(
        json.dumps(sisi, sort_keys=True, indent=4))
Exemplo n.º 12
0
def tq_status(*_):
    """Display current status of Tranquility, the main game server."""

    tq = do_request("{}/dev/status/".format(ESI))[1]
    return "Tranquility status: ```{}```".format(
        json.dumps(tq, sort_keys=True, indent=4))
Exemplo n.º 13
0
def server_status(datsource):
    """Generate a reply describing the status of an EVE server/datasource."""

    if datsource == "tranquility":
        base_url = ESI
    elif datsource == "serenity":
        base_url = ESI_CHINA
    else:
        return "Cannot request server status for `{}`".format(datsource)

    status_code, response = do_request("{}/v1/status/?datasource={}".format(
        base_url,
        datsource,
    ))
    server_name = datsource.capitalize()

    if status_code == 200:
        start_time = datetime.strptime(
            response["start_time"],
            "%Y-%m-%dT%H:%M:%SZ",
        )
        vip = response.get("vip")  # pylint: disable=no-member
        attachment = {
            "color":
            "warning" if vip else "good",
            "title":
            "{} status".format(server_name),
            "fields": [
                {
                    "title": "Players online",
                    "value": "{:,}".format(response["players"]),
                },
                {
                    "title": "Started at",
                    "value": response["start_time"],
                    "short": True,
                },
                {
                    "title": "Running for",
                    "value": _running_for(start_time),
                    "short": True,
                },
            ],
            "fallback":
            "{} status: {:,} online, started at {}{}".format(
                server_name,
                response["players"],
                response["start_time"],
                ", in VIP" * int(vip is True),
            ),
        }
        if vip:
            attachment["fields"].insert(0, {"title": "In VIP mode"})

    elif status_code == 503:
        attachment = {
            "color": "danger",
            "title": "{} status".format(server_name),
            "text": "Offline",
            "fallback": "{} status: Offline".format(server_name),
        }
    else:
        indeterminate = (
            "Cannot determine server status. "
            "It might be offline, or experiencing connectivity issues.")
        attachment = {
            "color": "danger",
            "title": "{} status".format(server_name),
            "text": indeterminate,
            "fallback": "{} status: {}".format(server_name, indeterminate),
        }

    return REPLY(content=None, attachments=[attachment])
Exemplo n.º 14
0
def request(match, msg):
    """Make an ESI GET request, if the path is known.

    Options:
        --headers    nest the response and add the headers
    """

    match_group = match.groupdict()

    if "evepc.163.com" in (match_group["esi"] or ""):
        base_url = ESI_CHINA
    else:
        base_url = esi_base_url(msg)

    version, *req_sections = match_group["esi_path"].split("/")
    if version not in ESI_SPECS[base_url]:
        req_sections.insert(0, version)
        version = "latest"

    params = ""
    if "?" in req_sections[-1]:
        if req_sections[-1].startswith("?"):
            params = req_sections.pop()
            params = params[1:]
        else:
            # qsparams passed w/out trailing slash
            final_path, params = req_sections.pop().split("?")
            req_sections.append(final_path)

    params = html.unescape(params)
    path = "/{}/".format("/".join(x for x in req_sections if x))
    if _valid_path(base_url, path, version):
        url = "{}/{}{}{}{}".format(
            base_url,
            version,
            path,
            "?" * int(params != ""),
            params,
        )
        start = time.time()
        res = do_request(url, return_response=True)

        try:
            content = res.json()
        except ValueError:
            content = res.text

        try:
            status = http.HTTPStatus(res.status_code)  # pylint: disable=E1120
        except ValueError:
            status = str(res.status_code)
        else:
            status = "{} {}".format(status.value, status.name)  # pylint: disable=E1101

        if "--headers" in msg.args:
            res = {"response": content, "headers": dict(res.headers)}
        else:
            res = content

        return SNIPPET(
            content=json.dumps(res, sort_keys=True, indent=4),
            filename="response.json",
            filetype="json",
            comment="{} ({:,.0f}ms)".format(
                status,
                (time.time() - start) * 1000,
            ),
            title=url,
        )

    return "failed to find GET {} in the {} ESI{} spec".format(
        path,
        version,
        " China" * int(base_url == ESI_CHINA),
    )