示例#1
0
def get_aqi_data(response_data: Dict, query: str) -> List[Tuple[str, str]]:
    """
    Grabs aqi data and station name from the response payload.

    Args:
        response_data: Response data from the API.
        query: search query from user.
    """
    data_store: List[Tuple[str, str]] = []
    AirData = namedtuple("AirData", ["station", "aqi"])

    data_node: List[Dict[str, str]] = response_data.get("data")

    # Check for empty data_node: []
    if not data_node:
        console.print(
            f"No air quality data found for search: [bold red]{query}[/bold red]"
        )
        sys.exit()

    # Grab aqi value and station name from the response payload.
    for item in data_node:
        aqi = item["aqi"]

        station = item["station"]["name"]
        data_package = AirData(station, aqi)
        data_store.append(data_package)

    return data_store
示例#2
0
def get_stations(data: Dict) -> List[NamedTuple]:
    """
    Get stations from the response payload.
    """
    Stations = namedtuple("Stations", ["uid", "station"])
    help_message = "No stations found in the location.:x:"

    data_node: List = data["data"]

    if not data_node:
        console.print(help_message)
        sys.exit()

    data_store = []
    for item in data_node:
        aqi = item["aqi"]

        uid = item["uid"]
        station = item["station"]["name"]
        data_store.append(Stations(uid, station))

    # When aqi value for stations are "-" data_store will be empty.
    if not data_store:
        console.print(help_message)
        sys.exit()

    return data_store
示例#3
0
def check_configs():
    """
    Checks if both the config directory and credential config are present.
    """
    if not os.path.exists(_CONFIG_DIR) or not check_credential_file:
        console.print(
            "You have not initialized the app, [bold green]use `air init` to add token[/bold green]"
        )
        sys.exit()
示例#4
0
def init():
    """
    Initialize the CLI by prompting the user to enter API token.
    """
    console.print(TOKEN_HELP_MSG)
    token = Prompt.get_input(
        console, ":key: Enter your API Token (hidden) ", password=True
    )

    # Store credential to ~/.aqi/creds file.
    add_credential(token)
示例#5
0
def remove_from_config_file(
    *, station_uid: List[int], location: str, station: str
):
    """
    Remove station from config file.

    Args:
        * : all arguments after this should be keyword arguments.

        station_uid: unique identifier for the station.
        location: search query entered by user.
        station: name of the station.
    """
    success_message = f"Successfully removed {station}!"
    empty_message = f"Config file empty. No stations saved to remove!"
    no_location_message = f"Location {location} isn't saved in config file."
    no_station_message = f"Station {station} isn't saved in config file."

    # Check for both config folder and credentials file.
    check_configs()

    # Remove uid from the config file.
    with open(CONFIG_FILE, "r+") as file:
        data = file.readline()

        if not data:
            console.print(empty_message)
            sys.exit()

        data_dict = json.loads(data)

        # If location doesnt exist, display message
        # If location exists but station doesnt, display message
        # If location exists as well as station, then remove the uid of the station
        if location not in data_dict:
            console.print(no_location_message)
            sys.exit()
        elif station_uid[0] not in data_dict[location]:
            console.print(station_uid[0])
            console.print(no_station_message)
            sys.exit()
        else:
            data_dict[location].remove(station_uid[0])

    with open(CONFIG_FILE, "w") as file:
        # Rewriting the config dictionary with config value
        file.seek(0)
        json.dump(data_dict, file)

    console.print(success_message)
示例#6
0
def add_credential(credential: str):
    """
    Store creds in .aqi/creds
    """
    # Create a config directory if it doesn't exist.
    if not os.path.exists(_CONFIG_DIR):
        os.mkdir(_CONFIG_DIR)

    # @TODO add hashing to encrypt the keys.
    # Write credentials to the file.
    with open(f"{CREDS_FILE}", "w+") as cred:
        cred.write(credential.strip())

    console.print(
        f"Credentials saved to [bold blue]{CREDS_FILE}[/bold blue]:white_check_mark:",
        style="bold green",
    )
示例#7
0
def show_table(data: List[Tuple]):
    """
    Show table to preview data.

    Args:
        data: Air Quality information.
    """
    table = Table(
        *TABLE_HEADERS,
        header_style="bold",
        title="Air Quality Index",
        title_style="bold black on white",
        box=box.ROUNDED,
        show_lines=True,
    )

    for row in data:
        table.add_row(*row)

    console.print(table)
示例#8
0
def add_to_config_file(*, station_uid: List[int], location: str, station: str):
    """
    Add station to config file.

    Args:
        * : all arguments after this should be keyword arguments.

        station_uid: unique identifier for the station.
        location: search query entered by user.
        station: name of the station.
    """
    help_message = f"Successfully added {station}!"

    # Check for both config folder and credentials file.
    check_configs()

    # Create stations config file if it does not exist.
    if not os.path.exists(CONFIG_FILE):
        with open(CONFIG_FILE, "w+"):
            pass

    # Add search query and uid to config dictionary.
    with open(CONFIG_FILE, "r+") as file:
        data = file.readline()

        # If config file empty.
        if not data:
            value = {location: station_uid}
            json.dump(value, file)

            console.print(help_message)
            sys.exit()

        data_dict = json.loads(data)

        # If key for search location does not exist, add station based on it.
        # Else check if uid for the search query already exists.
        # Else assume the key for the search query exists; append uid to its value (List).
        if location not in data_dict:
            data_dict[location] = station_uid
        elif station_uid[0] in data_dict[location]:
            console.print(f"Station: {station} already exists.")
            sys.exit()
        else:
            data_dict[location].append(station_uid[0])

        # Rewrite the config dictionary with updated value.
        file.seek(0)
        json.dump(data_dict, file)

    console.print(help_message)
示例#9
0
def get_config_stations() -> Dict[str, List[int]]:
    """
    Reads the config dictionary from the file.
    """
    help_msg = "You have not saved any stations, use [bold green]`air add <location>`[/bold green] to save a station!"

    if not os.path.exists(_CONFIG_DIR):
        console.print(
            "App is not initialized. Use [bold green]`air init`[/bold green] to get started!"
        )
        sys.exit()

    if not os.path.exists(CONFIG_FILE):
        console.print(help_msg)
        sys.exit()

    with open(CONFIG_FILE, "r") as file:
        data = json.loads(file.readline())

        if not data:
            console.print(help_msg)
            sys.exit()

        return data
示例#10
0
def make_request(query: str) -> Dict[str, str]:
    """
    Make an API request.

    Args:
        query: search query from user input.
    """
    token = check_credential_file()

    if not token:
        console.print(
            ":key: [bold red]No API token found, use [green]`air init`[/green] to enter API key.[/bold red]"
        )
        sys.exit()

    try:
        response = requests.get(
            BASE_URL.format(query=query, API_KEY=token),
            timeout=10,
        )
        response.raise_for_status()

        if response.json().get("status") == "error":
            raise requests.exceptions.HTTPError

    except requests.exceptions.HTTPError:
        error = response.json().get("data")
        console.print(
            f"Error: {error}.:x:",
            style="bold red",
        )

        sys.exit()
    except requests.exceptions.ConnectionError:
        console.print("[bold red]No connection:x:[/bold red]")
        sys.exit()
    except requests.exceptions.RequestException:
        console.print(
            "An error has occcured. Please try again later or open an issue on GitHub.:x:",
            style="bold red",
        )
        sys.exit()
    except requests.exceptions.ReadTimeout:
        console.print("Network connection timeout.:construction:",
                      style="bold red")

        sys.exit()

    except Exception:
        error_base = response.json().get("errors")[0]

        console.print(
            f"Error: {error_base.get('message')}:x:",
            style="bold red",
        )

        sys.exit()

    return response.json()