예제 #1
0
def process_new():
    """Process all new tokens, verify or we're done early."""

    for new_key in utils.list_keys(Keys.new.value):
        uuid = new_key.split(".")[-1]
        LOG.warning("processing new uuid: %r", uuid)

        token = CACHE.get(new_key)
        CACHE.delete(new_key)

        if not token:
            LOG.warning("no token stored for uuid: %r", uuid)
            continue

        pending_key = "{}{}".format(Keys.pending.value, uuid)
        CACHE.set(
            pending_key,
            "1",
            timeout=70,
        )
        headers = {"Authorization": "Bearer {}".format(token)}
        _, res = utils.request_or_wait(
            "{}/verify/".format(ESI),
            headers=headers,
        )

        failed = False
        if isinstance(res, str) or "CharacterID" not in res:
            utils.write_data(uuid, {"auth failure": res})
            failed = True
        else:
            _, roles = utils.request_or_wait(
                "{}/latest/characters/{}/roles/".format(
                    ESI,
                    res["CharacterID"],
                ),
                headers=headers,
            )
            if isinstance(roles, str):
                utils.write_data(uuid, {"roles failure": roles})
                failed = True

        CACHE.delete(pending_key)

        if not failed:
            CACHE.set(
                "{}{}".format(Keys.processing.value, uuid),
                res["CharacterID"],
                timeout=7200,
            )

            WORKERS.append(
                gevent.spawn(knife, uuid, token, res, roles)
            )
예제 #2
0
def knife(uuid, token, verify, roles):  # pylint: disable=R0914
    """Pull all ESI data for a character_id.

    Args:
        uuid: string uuid token
        token: SSO access token
        verify: dictionary return from /verify/
        roles: list of corporation roles
    """

    character_id = verify["CharacterID"]
    LOG.info("knife run started for character: %s", character_id)

    scopes = verify["Scopes"]

    _, _, public = utils.request_or_wait(
        "{}/latest/characters/{}/".format(ESI, character_id)
    )

    if isinstance(public, str):
        CACHE.delete("{}{}".format(Keys.processing.value, uuid))
        utils.write_data(uuid, {"public info failure": public})
        return

    headers = {"Authorization": "Bearer {}".format(token)}
    results = get_results(public, character_id, scopes, roles, headers)

    utils.write_data(uuid, results)
    CACHE.delete("{}{}".format(Keys.processing.value, uuid))
    CACHE.cache.inc(Keys.alltime.value, 1)
    LOG.info("completed character: %r", character_id)
예제 #3
0
def _get_names(ids):
    """Resolve ids to names."""

    resolved = {}
    failed = []
    for i in range(0, len(ids), 1000):
        batch = ids[i:i+1000]
        _, _, res = utils.request_or_wait(
            "{}/latest/universe/names/".format(ESI),
            method="post",
            json=batch,
        )
        if isinstance(res, list):
            for _res in res:
                resolved[_res["id"]] = _res["name"]
        else:
            failed.extend(batch)

    while failed:
        still_failed = []
        random.shuffle(failed)
        batch_size = max(min(int(len(failed) / 2), 500), 1)
        for i in range(0, len(failed), batch_size):
            batch = failed[i:i+batch_size]

            _, _, res = utils.request_or_wait(
                "{}/latest/universe/names/".format(ESI),
                method="post",
                json=batch,
            )
            if isinstance(res, list):
                for _res in res:
                    resolved[_res["id"]] = _res["name"]
            else:
                still_failed.extend(batch)

        failed = still_failed

        if batch_size == 1 and still_failed:
            LOG.warning("failed to resolve: %r", still_failed)
            break

    return resolved
예제 #4
0
def verify_token(headers):
    """Verify the access token.

    Args:
        headers: http request headers

    Returns:
        integer character ID, list of scopes

    Raises:
        SystemExit on error
    """

    _, _, res = request_or_wait("{}/verify/".format(ESI), headers=headers)

    if isinstance(res, dict) and "Scopes" in res and res["Scopes"] \
            and "CharacterID" in res and res["CharacterID"]:
        return res["CharacterID"], res["Scopes"]

    raise SystemExit("Could not find scopes in access token")
예제 #5
0
def run(args):
    """Create a new knife file."""

    token = get_access_token(args["--client-id"], args["--port"])

    headers = {"Authorization": "Bearer {}".format(token)}
    character_id, scopes = verify_token(headers)

    _, _, public = request_or_wait(
        "{}/latest/characters/{}/".format(ESI, character_id)
    )

    if isinstance(public, str):
        raise SystemExit("Failed to look up public info for: {}".format(
            character_id
        ))

    roles = get_roles(headers, character_id)

    results = get_results(public, character_id, scopes, roles, headers)

    write_results(results, character_id)
예제 #6
0
def get_roles(headers, character_id):
    """Determine the character's roles.

    Args:
        headers: http request headers
        character_id: integer character ID

    Returns:
        list of roles

    Raises:
        SystemExit on error
    """

    _, _, res = request_or_wait(
        "{}/latest/characters/{}/roles/".format(ESI, character_id),
        headers=headers,
    )

    if isinstance(res, dict):
        return res.get("roles", [])

    raise SystemExit("Could not deterine character's corporation roles")
예제 #7
0
def knife(uuid, token, verify, roles):  # pylint: disable=R0914
    """Pull all ESI data for a character_id.

    Args:
        uuid: string uuid token
        token: SSO access token
        verify: dictionary return from /verify/
        roles: list of corporation roles
    """

    character_id = verify["CharacterID"]
    LOG.warning("knife run started for character: %s", character_id)

    scopes = verify["Scopes"]

    _, public = utils.request_or_wait(
        "{}/latest/characters/{}/".format(ESI, character_id)
    )

    if isinstance(public, str):
        CACHE.delete("{}{}".format(Keys.processing.value, uuid))
        utils.write_data(uuid, {"public info failure": public})
        return

    all_params = copy.deepcopy(ADDITIONAL_PARAMS)

    known_params = {"character_id": character_id}

    if public["corporation_id"] > 2000000:
        known_params["corporation_id"] = public["corporation_id"]
    else:
        all_params.pop("corporation_id")

    if "alliance_id" in public:
        known_params["alliance_id"] = public["alliance_id"]

    spec = utils.refresh_spec()
    headers = {"Authorization": "Bearer {}".format(token)}

    results = expand_params(
        scopes,
        roles,
        spec,
        known_params,
        all_params,
        headers,
    )

    urls = build_urls(scopes, roles, spec, known_params, all_params)

    with ThreadPoolExecutor(max_workers=20) as pool:
        futures = []
        for url in urls:
            futures.append(pool.submit(
                utils.request_or_wait,
                url,
                headers=headers,
            ))

        for future in as_completed(futures):
            url, result = future.result()
            results[url] = result

    utils.write_data(uuid, results)
    CACHE.delete("{}{}".format(Keys.processing.value, uuid))
    LOG.warning("completed character: %r", character_id)