Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: elisiariocouto/leggen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.6.4
Choose a base ref
...
head repository: elisiariocouto/leggen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
  • 17 commits
  • 11 files changed
  • 1 contributor

Commits on Jul 5, 2024

  1. Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    758a3a2 View commit details
  2. Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    effabf0 View commit details
  3. chore(ci): Bump version to 0.6.5

    elisiariocouto committed Jul 5, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    a8fb3ad View commit details

Commits on Aug 21, 2024

  1. Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    a29bd1a View commit details
  2. fix(commands/status): Handle exception when no last_accessed is ret…

    …urned from GoCardless API.
    elisiariocouto committed Aug 21, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    c70a4e5 View commit details
  3. Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    5934633 View commit details
  4. chore(ci): Bump version to 0.6.6

    elisiariocouto committed Aug 21, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    e7662bc View commit details

Commits on Sep 15, 2024

  1. Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    7efbccf View commit details
  2. Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    75ca7f1 View commit details
  3. chore(ci): Bump version to 0.6.7

    elisiariocouto committed Sep 15, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    6b2cb8a View commit details

Commits on Jan 13, 2025

  1. Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    33006f8 View commit details
  2. Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    eb73401 View commit details
  3. chore(ci): Bump version to 0.6.8

    elisiariocouto committed Jan 13, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    4ed1bf5 View commit details

Commits on Jan 14, 2025

  1. Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    ca29d52 View commit details
  2. chore(ci): Bump version to 0.6.9

    elisiariocouto committed Jan 14, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    d69bd5d View commit details
  3. Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    7480094 View commit details
  4. chore(ci): Bump version to 0.6.10

    elisiariocouto committed Jan 14, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    elisiariocouto Elisiário Couto
    Copy the full SHA
    7cf4714 View commit details
Showing with 554 additions and 725 deletions.
  1. +28 −15 .github/workflows/release.yml
  2. +3 −8 .pre-commit-config.yaml
  3. +64 −0 CHANGELOG.md
  4. +18 −13 Dockerfile
  5. +5 −1 leggen/commands/status.py
  6. +21 −23 leggen/commands/sync.py
  7. +24 −9 leggen/notifications/telegram.py
  8. +0 −623 poetry.lock
  9. +36 −29 pyproject.toml
  10. +4 −4 scripts/release.sh
  11. +351 −0 uv.lock
43 changes: 28 additions & 15 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -6,28 +6,41 @@ on:
- "**"

jobs:
publish-pypi:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version: "3.12"

python-version-file: "pyproject.toml"
- name: Build Package
run: |
python -m pip install --upgrade pip
pip install poetry
poetry config virtualenvs.create false
poetry build -f wheel
run: uv build
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/

publish-to-pypi:
name: Publish Python distribution to PyPI
runs-on: ubuntu-latest
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
needs:
- build
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Publish package
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }}
run: poetry publish
run: uv publish

push-docker:
runs-on: ubuntu-latest
11 changes: 3 additions & 8 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
repos:
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
language_version: python3.12
- repo: https://github.com/charliermarsh/ruff-pre-commit
# Ruff version.
rev: "v0.4.8"
rev: "v0.9.1"
hooks:
- id: ruff
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v5.0.0
hooks:
- id: trailing-whitespace
exclude: ".*\\.md$"
64 changes: 64 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,67 @@

## 0.6.10 (2025/01/14)

### Bug Fixes

- **ci:** Install uv before publishing. ([74800944](https://github.com/elisiariocouto/leggen/commit/7480094419697a46515a88a635d4e73820b0d283))



## 0.6.9 (2025/01/14)

### Miscellaneous Tasks

- Setup PyPI Trusted Publishing. ([ca29d527](https://github.com/elisiariocouto/leggen/commit/ca29d527c9e5f9391dfcad6601ad9c585b511b47))



## 0.6.8 (2025/01/13)

### Miscellaneous Tasks

- Migrate from Poetry to uv, bump dependencies and python version. ([33006f8f](https://github.com/elisiariocouto/leggen/commit/33006f8f437da2b9b3c860f22a1fda2a2e5b19a1))
- Fix typo in release script. ([eb734018](https://github.com/elisiariocouto/leggen/commit/eb734018964d8281450a8713d0a15688d2cb42bf))



## 0.6.7 (2024/09/15)

### Bug Fixes

- **notifications/telegram:** Escape characters when notifying via Telegram. ([7efbccfc](https://github.com/elisiariocouto/leggen/commit/7efbccfc90ea601da9029909bdd4f21640d73e6a))


### Miscellaneous Tasks

- Bump dependencies. ([75ca7f17](https://github.com/elisiariocouto/leggen/commit/75ca7f177fb9992395e576ba9038a63e90612e5c))



## 0.6.6 (2024/08/21)

### Bug Fixes

- **commands/status:** Handle exception when no `last_accessed` is returned from GoCardless API. ([c70a4e5c](https://github.com/elisiariocouto/leggen/commit/c70a4e5cb87a19a5a0ed194838e323c6246856ab))
- **notifications/telegram:** Escape parenthesis. ([a29bd1ab](https://github.com/elisiariocouto/leggen/commit/a29bd1ab683bc9e068aefb722e9e87bb4fe6aa76))


### Miscellaneous Tasks

- Update dependencies, use ruff to format code. ([59346334](https://github.com/elisiariocouto/leggen/commit/59346334dbe999ccfd70f6687130aaedb50254fa))


## 0.6.5 (2024/07/05)

### Bug Fixes

- **sync:** Continue on account deactivation. ([758a3a22](https://github.com/elisiariocouto/leggen/commit/758a3a2257c490a92fb0b0673c74d720ad7e87f7))


### Miscellaneous Tasks

- Bump dependencies. ([effabf06](https://github.com/elisiariocouto/leggen/commit/effabf06954b08e05e3084fdbc54518ea5d947dc))


## 0.6.4 (2024/06/07)

### Bug Fixes
31 changes: 18 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
FROM python:3.12-alpine as builder
ARG POETRY_VERSION="1.7.1"
FROM python:3.13-alpine AS builder
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

WORKDIR /app
RUN apk add --no-cache gcc libffi-dev musl-dev && \
pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -q poetry=="${POETRY_VERSION}"
COPY . .
RUN poetry config virtualenvs.create false && poetry build -f wheel

FROM python:3.12-alpine
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --frozen --no-install-project --no-editable

COPY . /app

RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-editable

FROM python:3.13-alpine

LABEL org.opencontainers.image.source="https://github.com/elisiariocouto/leggen"
LABEL org.opencontainers.image.authors="Elisiário Couto <elisiario@couto.io>"
@@ -17,8 +22,8 @@ LABEL org.opencontainers.image.title="leggen"
LABEL org.opencontainers.image.description="An Open Banking CLI"
LABEL org.opencontainers.image.url="https://github.com/elisiariocouto/leggen"

WORKDIR /app
COPY --from=builder /app/dist/ /app/
RUN pip --no-cache-dir install leggen*.whl && \
rm leggen*.whl
ENTRYPOINT ["/usr/local/bin/leggen"]
# Copy the environment, but not the source code
COPY --from=builder --chown=app:app /app/.venv /app/.venv

# Run the application
ENTRYPOINT ["/app/.venv/bin/leggen"]
6 changes: 5 additions & 1 deletion leggen/commands/status.py
Original file line number Diff line number Diff line change
@@ -39,7 +39,11 @@ def status(ctx: click.Context):
"Status": details["status"],
"IBAN": details.get("iban", "N/A"),
"Created at": datefmt(details["created"]),
"Last accessed at": datefmt(details["last_accessed"]),
"Last accessed at": (
datefmt(details["last_accessed"])
if details.get("last_accessed")
else "N/A"
),
}
)
echo()
44 changes: 21 additions & 23 deletions leggen/commands/sync.py
Original file line number Diff line number Diff line change
@@ -41,30 +41,28 @@ def sync(ctx: click.Context):
info(f"Syncing balances for {len(accounts)} accounts")

for account in accounts:
account_details = get(ctx, f"/accounts/{account}")
account_balances = get(ctx, f"/accounts/{account}/balances/").get(
"balances", []
)
for balance in account_balances:
balance_amount = balance["balanceAmount"]
amount = round(float(balance_amount["amount"]), 2)
balance_document = {
"account_id": account,
"bank": account_details["institution_id"],
"status": account_details["status"],
"iban": account_details.get("iban", "N/A"),
"amount": amount,
"currency": balance_amount["currency"],
"type": balance["balanceType"],
"timestamp": datetime.datetime.now().timestamp(),
}
try:
try:
account_details = get(ctx, f"/accounts/{account}")
account_balances = get(ctx, f"/accounts/{account}/balances/").get(
"balances", []
)
for balance in account_balances:
balance_amount = balance["balanceAmount"]
amount = round(float(balance_amount["amount"]), 2)
balance_document = {
"account_id": account,
"bank": account_details["institution_id"],
"status": account_details["status"],
"iban": account_details.get("iban", "N/A"),
"amount": amount,
"currency": balance_amount["currency"],
"type": balance["balanceType"],
"timestamp": datetime.datetime.now().timestamp(),
}
persist_balance(ctx, account, balance_document)
except Exception as e:
error(
f"[{account}] Error: Sync failed, skipping account, exception: {e}"
)
continue
except Exception as e:
error(f"[{account}] Error: Sync failed, skipping account, exception: {e}")
continue

info(f"Syncing transactions for {len(accounts)} accounts")

33 changes: 24 additions & 9 deletions leggen/notifications/telegram.py
Original file line number Diff line number Diff line change
@@ -7,11 +7,24 @@
def escape_markdown(text: str) -> str:
return (
str(text)
.replace("-", "\\-")
.replace("_", "\\_")
.replace("*", "\\*")
.replace("[", "\\[")
.replace("]", "\\]")
.replace("(", "\\(")
.replace(")", "\\)")
.replace("~", "\\~")
.replace("`", "\\`")
.replace(">", "\\>")
.replace("#", "\\#")
.replace(".", "\\.")
.replace("$", "\\$")
.replace("+", "\\+")
.replace("-", "\\-")
.replace("=", "\\=")
.replace("|", "\\|")
.replace("{", "\\{")
.replace("}", "\\}")
.replace(".", "\\.")
.replace("!", "\\!")
)


@@ -21,13 +34,15 @@ def send_expire_notification(ctx: click.Context, notification: dict):
bot_url = f"https://api.telegram.org/bot{token}/sendMessage"
info("Sending expiration notification to Telegram")
message = "*💲 [Leggen](https://github.com/elisiariocouto/leggen)*\n"
message += f"Your account {notification['bank']} ({notification['requisition_id']}) is in {notification['status']} status. Days left: {notification['days_left']}\n"
message += escape_markdown(
f"Your account {notification['bank']} ({notification['requisition_id']}) is in {notification['status']} status. Days left: {notification['days_left']}\n"
)

res = requests.post(
bot_url,
json={
"chat_id": chat_id,
"text": escape_markdown(message),
"text": message,
"parse_mode": "MarkdownV2",
},
)
@@ -47,15 +62,15 @@ def send_transaction_message(ctx: click.Context, transactions: list):
message += f"{len(transactions)} new transaction matches\n\n"

for transaction in transactions:
message += f"*Name*: {transaction['name']}\n"
message += f"*Value*: {transaction['value']}{transaction['currency']}\n"
message += f"*Date*: {transaction['date']}\n\n"
message += f"*Name*: {escape_markdown(transaction['name'])}\n"
message += f"*Value*: {escape_markdown(transaction['value'])}{escape_markdown(transaction['currency'])}\n"
message += f"*Date*: {escape_markdown(transaction['date'])}\n\n"

res = requests.post(
bot_url,
json={
"chat_id": chat_id,
"text": escape_markdown(message),
"text": message,
"parse_mode": "MarkdownV2",
},
)
Loading