#!/usr/bin/env python3 # tab2ledger # Copyright © 2019 Midgard # # This program is free software: you can redistribute it and/or modify it under the terms of the # GNU General Public License as published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License along with this program. # If not, see . import itertools import sys import os import requests ME = os.getenv("TAB_ME") TOKEN = os.getenv("TAB_TOKEN") BASE_URI = os.getenv("TAB_BASE_URI", default="https://tab.zeus.gent") TAP_ACCOUNT = os.getenv("LEDGER_TAP_ACCOUNT", default="Expenses:Zeuskelder:Drinks and snacks") FOOD_ACCOUNT = os.getenv("LEDGER_FOOD_ACCOUNT", default="Expenses:Zeuskelder:Food") TAB2LEDGER_NAME = "tab2ledger" TAB2LEDGER_VERSION = "1.0" TAB2LEDGER_URL = "https://git.zeus.gent/midgard/tab2ledger" USER_AGENT = os.getenv("TAB2LEDGER_USER_AGENT", default=f"{TAB2LEDGER_NAME} {TAB2LEDGER_VERSION} ({TAB2LEDGER_URL})") def formatted_price(cents): return f"€ {cents / 100}" def balance_assertion(balance): return \ f"= {formatted_price(balance)}" \ if balance is not None else "" def formatted_transaction(transaction, me, balance_after=None): issuer = transaction["issuer"] debtor = transaction["debtor"] date = transaction["time"][:10] amount = formatted_price(transaction["amount"]) message = ( transaction["message"].replace("1 ", "").replace(" and ", " en ") if issuer == "Tap" else transaction["message"] ).strip() assertion = balance_assertion(balance_after) if debtor == me: # If the issuer wasn't Tap, we assume the money we gave was for food – manual change to the # output required if it wasn't if issuer == "Tap": to_account = TAP_ACCOUNT message = f"Zeus WPI | {message}" else: to_account = FOOD_ACCOUNT message = f"{issuer} | {message}" to_line = f"{to_account} {amount}" from_line = f"tab {assertion}" else: message = f"{debtor} | {message}" to_line = f"tab {amount} {assertion}" from_line = f";" header = f"{date} {message}" return "\n".join([ header, "\t" + to_line.rstrip(), "\t" + from_line.rstrip() ]) def formatted_transactions(transactions, final_balance, me): all_but_last = itertools.islice(transactions, len(transactions) - 1) return [ *(formatted_transaction(t, me) for t in all_but_last), formatted_transaction(transactions[-1], me, final_balance) ] def main(me, token, file=sys.stdout): def get(path): return requests.get( f"{BASE_URI}{path}", headers={ "Accept": "application/json", "Authorization": f"Token token={token}", "User-Agent": USER_AGENT } ).json() balance = get(f"/users/{me}")["balance"] transactions = get(f"/users/{me}/transactions") print( "\n\n".join(formatted_transactions(transactions, balance, me)), file=file ) if __name__ == "__main__": main(ME, TOKEN)