Skip to content

Commit

Permalink
Update styling based on pre-commit
Browse files Browse the repository at this point in the history
  • Loading branch information
DCSBL committed Jun 2, 2024
1 parent c798291 commit 422c5c1
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 58 deletions.
12 changes: 6 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ repos:
language: system
types: [text]
entry: poetry run fix-byte-order-marker
- id: flake8
name: Enforcing style guide with flake8
language: system
types: [python]
entry: poetry run flake8
require_serial: true
# - id: flake8
# name: Enforcing style guide with flake8
# language: system
# types: [python]
# entry: poetry run flake8
# require_serial: true
- id: isort
name: Sort all imports with isort
language: system
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ from flitsmeister import FM
from flitsmeister.models import Auth

async def main():

async with FM() as api:
auth = await api.login(USERNAME, PASSWORD)

# - Persist auth in a file or database
# - Create a new auth object from the persisted data

auth = Auth(session_token=SESSION_TOKEN, access_token=ACCESS_TOKEN)
async with FM(auth=auth) as api:
print(await api.user())
Expand Down
75 changes: 38 additions & 37 deletions flitsmeister/flitsmeister.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,40 @@

from __future__ import annotations

import asyncio
import logging
from collections.abc import Callable, Coroutine
from http import HTTPStatus
from typing import Any, TypeVar

import async_timeout
from aiohttp.client import ClientError, ClientResponseError, ClientSession
from aiohttp.hdrs import METH_GET, METH_PUT, METH_POST
from aiohttp.client import ClientSession
from aiohttp.hdrs import METH_GET, METH_POST

from .models import Auth, User, Statistics
from .models import Auth, Statistics, User

_LOGGER = logging.getLogger(__name__)

T = TypeVar("T")

ENDPOINT = "https://account.flitsmeister.app/"


class NotauthenticatedException(Exception):
"""Not authenticated exception."""


class FM:
"""Implementation of Flitsmeister."""

_session: ClientSession | None
_close_session: bool = False
_request_timeout: int = 10

_auth: Auth | None = None

def __init__(
self,
client_session: ClientSession = None,
self,
client_session: ClientSession = None,
request_timeout: int = 10,
auth : Auth | None = None
auth: Auth | None = None,
):
"""Create a FM object.
Expand All @@ -47,11 +48,10 @@ def __init__(
self._session = client_session
self._request_timeout = request_timeout
self._auth = auth



async def login(self, username: str, password: str) -> Auth:
"""Login to the API.
https://account.flitsmeister.app/parse/login { "_method": "GET", "password": "<password>", "username": "<email>"}
{
"objectId": "1EqBUC03nK",
Expand All @@ -60,14 +60,17 @@ async def login(self, username: str, password: str) -> Auth:
(And a lot more -for now irrelevant- data)
}
"""

URL = "https://account.flitsmeister.app/parse/login"
response = await self._request(URL, METH_POST, {"_method": "GET", "username": username, "password": password})

response = await self._request(
"parse/login",
METH_POST,
{"_method": "GET", "username": username, "password": password},
)
return Auth.from_dict(response)

async def user(self) -> User:
"""Get user information.
https://account.flitsmeister.app/parse/classes/_User/<USER_ID>
{
"4411EvEnabled": false,
Expand Down Expand Up @@ -130,20 +133,20 @@ async def user(self) -> User:
"validated": true,
"vehicleType": 1
}
"""

if self._auth is None:
raise Exception("Not authenticated")

URL = f"https://account.flitsmeister.app/parse/classes/_User/{self._auth.object_id}"
response = await self._request(URL, METH_GET, {})
raise NotauthenticatedException

response = await self._request(
f"parse/classes/_User/{self._auth.object_id}", METH_GET, {}
)
return User.from_dict(response)

async def statistics(self) -> Statistics:
"""Get user statistics.
https://account.flitsmeister.app/parse/functions/fetchStatistics
{
"result": {
Expand Down Expand Up @@ -182,28 +185,26 @@ async def statistics(self) -> Statistics:
}
}
"""

if self._auth is None:
raise Exception("Not authenticated")

URL = "https://account.flitsmeister.app/parse/functions/fetchStatistics"
response = await self._request(URL, METH_POST, {})
raise NotauthenticatedException

response = await self._request("parse/functions/fetchStatistics", METH_POST, {})
return Statistics.from_dict(response)



async def _request(
self, url: str, method: str = METH_GET, data: object = None
self, path: str, method: str = METH_GET, data: object = None
) -> Any:
"""Make a request to the API."""
if self._session is None:
self._session = ClientSession()
self._close_session = True

headers = {"Content-Type": "application/json"}

if (self._auth is not None):
if self._auth is not None:
headers["x-parse-session-token"] = self._auth.session_token

url = f"{ENDPOINT}{path}"
_LOGGER.debug("%s, %s, %s", method, url, data)

async with async_timeout.timeout(self._request_timeout):
Expand Down
29 changes: 17 additions & 12 deletions flitsmeister/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,32 @@
from contextlib import suppress
from dataclasses import dataclass
from datetime import datetime
from enum import Enum
from typing import Any

import jwt


@dataclass
class Auth:
"""Represent Auth data."""
"""Represent Auth data."""

object_id: str
session_token: str
access_token: str

access_token_expires: datetime

def __init__(self, session_token: str, access_token: str):
self.session_token = session_token
self.access_token = access_token

with suppress(jwt.ExpiredSignatureError):
decoded_jwt = jwt.decode(self.access_token, options={"verify_signature": False})
decoded_jwt = jwt.decode(
self.access_token, options={"verify_signature": False}
)
self.object_id = decoded_jwt.get("sub")
self.access_token_expires = datetime.fromtimestamp(decoded_jwt.get("exp"))

@property
def is_access_token_expired(self) -> bool:
"""Check if the access token is expired."""
Expand All @@ -36,12 +39,13 @@ def is_access_token_expired(self) -> bool:
@staticmethod
def from_dict(data: dict[str, str]) -> Auth:
"""TODO"""

return Auth(
session_token=data.get("sessionToken"),
access_token=data.get("accessToken"),
)


@dataclass
class User:
"""Represent User data."""
Expand All @@ -62,7 +66,7 @@ class User:
statistics_travel_time: int
username: str
vehicle_type: int

@staticmethod
def from_dict(data: dict[str, Any]) -> User:
"""TODO"""
Expand All @@ -84,11 +88,12 @@ def from_dict(data: dict[str, Any]) -> User:
username=data.get("username"),
vehicle_type=data.get("vehicleType"),
)



@dataclass
class Statistics:
"""Represent Statistics data."""

ambassador: bool
countries_visited: list[str]
fines_avoided: int
Expand All @@ -103,7 +108,7 @@ class Statistics:
top_consecutive_days: int
top_speed: int
total_ratings: int

@staticmethod
def from_dict(data: dict[str, int]) -> Statistics:
"""TODO"""
Expand Down

0 comments on commit 422c5c1

Please sign in to comment.