diff --git a/.gitignore b/.gitignore index 691037e..89930b5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .venv/* +.env diff --git a/bscan/__pycache__/__init__.cpython-311.pyc b/bscan/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..82999b2 Binary files /dev/null and b/bscan/__pycache__/__init__.cpython-311.pyc differ diff --git a/bscan/__pycache__/main.cpython-311.pyc b/bscan/__pycache__/main.cpython-311.pyc new file mode 100644 index 0000000..02fd6f8 Binary files /dev/null and b/bscan/__pycache__/main.cpython-311.pyc differ diff --git a/bscan/connector/__init__.py b/bscan/connector/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bscan/connector/__pycache__/__init__.cpython-311.pyc b/bscan/connector/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..0adf019 Binary files /dev/null and b/bscan/connector/__pycache__/__init__.cpython-311.pyc differ diff --git a/bscan/connector/__pycache__/common.cpython-311.pyc b/bscan/connector/__pycache__/common.cpython-311.pyc new file mode 100644 index 0000000..8d8a5fc Binary files /dev/null and b/bscan/connector/__pycache__/common.cpython-311.pyc differ diff --git a/bscan/connector/__pycache__/paperless.cpython-311.pyc b/bscan/connector/__pycache__/paperless.cpython-311.pyc new file mode 100644 index 0000000..987dfc1 Binary files /dev/null and b/bscan/connector/__pycache__/paperless.cpython-311.pyc differ diff --git a/bscan/connector/common.py b/bscan/connector/common.py new file mode 100644 index 0000000..f13a434 --- /dev/null +++ b/bscan/connector/common.py @@ -0,0 +1,56 @@ +from requests import Response, get, post +from abc import ABC, abstractmethod +from types import TracebackType +from typing import IO, Any, Self, final + + +class Connector(ABC): + @property + @abstractmethod + def connected(self) -> bool: + raise NotImplementedError + + @abstractmethod + def connect(self) -> None: + raise NotImplementedError + + @abstractmethod + def disconnect(self) -> None: + raise NotImplementedError + + @final + def __enter__(self) -> Self: + self.connect() + return self + + @final + def __exit__( + self, + _exc_type: type[BaseException] | None, + _exc_value: BaseException | None, + _exc_tb: TracebackType | None, + ) -> bool: + self.disconnect() + return False + + +class RESTConnector(Connector, ABC): + url: str + port: int + + def post( + self, + endpoint: str, + data: dict[str, Any], + files: dict[str, IO] | None = None, + header: dict[str, Any] | None = None, + ) -> Response: + return post( + f"https://{self.url}:{self.port}/{endpoint}", + data=data, + files=files, + headers=header, + ) + + def get(self, endpoint: str, data: dict[str, Any]) -> Response: + return get(f"https://{self.url}:{self.port}/{endpoint}", params=data) diff --git a/bscan/connector/paperless.py b/bscan/connector/paperless.py new file mode 100644 index 0000000..fc29a42 --- /dev/null +++ b/bscan/connector/paperless.py @@ -0,0 +1,62 @@ +from datetime import datetime +from typing import IO, NotRequired, TypedDict, Unpack + +from requests import Response +from .common import RESTConnector + + +class PaperlessPostDocumentOptions(TypedDict): + title: NotRequired[str] + created: NotRequired[datetime] + correspondent: NotRequired[str] + document_type: NotRequired[str] + tags: NotRequired[list[str]] + archive_serial_number: NotRequired[int] + + +class PaperlessConnection(RESTConnector): + url: str + port: int + + _token: str | None + + def __init__( + self, + url: str, + port: int, + user: str, + password: str, + ) -> None: + self.url = url + self.port = port + token_response = self.post( + "/api/token/", + { + "username": user, + "password": password, + }, + ) + + assert token_response.ok, token_response + + self._token = token_response.json()["token"] + + def post_document( + self, document: IO, **kwargs: Unpack[PaperlessPostDocumentOptions] + ) -> Response: + return self.post( + "/api/documents/post_document/", + files={"document": document}, + data=dict(**kwargs), + header={"Authorization": f"Token {self._token}"}, + ) + + @property + def connected(self) -> bool: + return bool(self._token) + + def connect(self) -> None: + pass + + def disconnect(self) -> None: + pass diff --git a/bscan/connector/scanner.py b/bscan/connector/scanner.py new file mode 100644 index 0000000..78e1d12 --- /dev/null +++ b/bscan/connector/scanner.py @@ -0,0 +1,5 @@ +from bscan.connector.common import Connector + + +class HPScannerConnection(Connector): + pass diff --git a/bscan/main.py b/bscan/main.py index 4693850..85281b4 100644 --- a/bscan/main.py +++ b/bscan/main.py @@ -1,5 +1,25 @@ +import sane as sane + + def main() -> None: - pass + # env_file = Path(__file__).parent.parent / ".env" + # + # if env_file.exists(): + # conf = loads(env_file.read_text()) + # user = conf["username"] + # password = conf["password"] + # else: + # user = input("paperless user: ") + # password = getpass("paperless password: ") + # + # pc = PaperlessConnection("papers.acereca.net", 443, user, password) + # + # doc = Path(__file__).parent.parent / "tests" / "data" / "20230504_FRITZ!Box7590.pdf" + # + # ret = pc.post_document(document=doc.open(mode="rb")) + + sane.init() + print(sane.get_devices()) if __name__ == "__main__": diff --git a/pyproject.toml b/pyproject.toml index aacdc3b..22bd6a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,10 @@ [project] name = "bscan" version = "0.1.0" -dependencies = [] +dependencies = [ + "requests~=2.31", + "python-sane~=2.9" +] [project.optional-dependencies] dev = [ @@ -18,4 +21,4 @@ requires = [ ] [project.scripts] -bscan = "bscan:main/main" +bscan = "bscan.main:main" diff --git a/tests/data/20230504_FRITZ!Box7590.pdf b/tests/data/20230504_FRITZ!Box7590.pdf new file mode 100644 index 0000000..48d311c Binary files /dev/null and b/tests/data/20230504_FRITZ!Box7590.pdf differ