コード例 #1
0
    def test_api_context_restore(self):
        """
        Saves an ApiContext to a temporary file, restores an ApiContext from
        that file, and compares whether the api_keys, tokens, and environment
        types are equal in the ApiContext and the restored ApiContext.

        Removes the temporary file before assertion.
        """

        self._API_CONTEXT.save(self._TMP_FILE_PATH_FULL)
        api_context_restored = ApiContext.restore(self._TMP_FILE_PATH_FULL)

        os.remove(self._TMP_FILE_PATH_FULL)

        self.assertEqual(api_context_restored, self._API_CONTEXT)
コード例 #2
0
    def setup_context(self):
        if isfile(self.determine_bunq_conf_filename()):
            pass  # Config is already present
        elif self.env == ApiEnvironmentType.SANDBOX:
            sandbox_user = self.generate_new_sandbox_user()
            ApiContext(ApiEnvironmentType.SANDBOX, sandbox_user.api_key,
                       socket.gethostname()).save(
                           self.determine_bunq_conf_filename())
        else:
            raise BunqException(self._ERROR_COULD_NOT_DETIRMINE_CONF)

        api_context = ApiContext.restore(self.determine_bunq_conf_filename())
        api_context.ensure_session_active()
        api_context.save(self.determine_bunq_conf_filename())

        BunqContext.load_api_context(api_context)
コード例 #3
0
    def setup_context(self):
        if Path(self.determine_bunq_conf_filename()).is_file():
            pass
        else:
            sandbox_user = self.generate_new_sandbox_user()
            ApiContext(
                ApiEnvironmentType.SANDBOX, sandbox_user.api_key, socket.gethostname()
            ).save(self.determine_bunq_conf_filename())

        self._api_context = ApiContext.restore(self.determine_bunq_conf_filename())
        self._api_context.ensure_session_active()
        self._api_context.save(self.determine_bunq_conf_filename())

        BunqContext.load_api_context(self._api_context)

        self._user_context = BunqContext.user_context()
コード例 #4
0
    def setup_context(self, reset_config_if_needed=True):
        if isfile(self.determine_bunq_conf_filename()):
            pass  # Config is already present
        elif self.env == ApiEnvironmentType.SANDBOX:
            sandbox_user = self.generate_new_sandbox_user()
            ApiContext(ApiEnvironmentType.SANDBOX, sandbox_user.api_key,
                       socket.gethostname()).save(
                           self.determine_bunq_conf_filename())
        else:
            raise BunqException(self._ERROR_COULD_NOT_DETERMINE_CONF)

        try:
            api_context = ApiContext.restore(
                self.determine_bunq_conf_filename())
            api_context.ensure_session_active()
            api_context.save(self.determine_bunq_conf_filename())

            BunqContext.load_api_context(api_context)
        except ForbiddenException as forbidden_exception:
            if reset_config_if_needed:
                self.__handle_forbidden_exception(forbidden_exception)
            else:
                raise forbidden_exception
コード例 #5
0
ファイル: app.py プロジェクト: Tobiaqs/balance-viewer-python
from bunq.sdk.client import Pagination
from bunq.sdk.context import ApiContext
from bunq.sdk.context import ApiEnvironmentType
from bunq.sdk.context import BunqContext
from bunq.sdk.model.generated import endpoint
from json import dumps

if "SECRET" not in environ:
    print("SECRET not specified. Exiting.")
    exit(0)

app = Flask(__name__)

CONTEXT_FILE = "bunq-production.conf"

api_context = ApiContext.restore(CONTEXT_FILE)
api_context.ensure_session_active()
api_context.save(CONTEXT_FILE)
BunqContext.load_api_context(api_context)

def get_all_monetary_account_active():
    pagination = Pagination()
    pagination.count = 25

    all_monetary_account_bank = endpoint.MonetaryAccountBank.list(pagination.url_params_count_only).value
    all_monetary_account_bank_active = []

    for monetary_account_bank in all_monetary_account_bank:
        if monetary_account_bank.status == "ACTIVE":
            all_monetary_account_bank_active.append(monetary_account_bank)
コード例 #6
0
ファイル: export.py プロジェクト: jorants/bunq-example-export
def all_transactions(dt=None):
    # This should be enough to ensure the whole account is included.
    if dt == None:
        dt = epoch

    env = ApiEnvironmentType.PRODUCTION

    if not isfile('bunq-production.conf'):
        raise Exception("No config file found, run start.py first.")

    # Reload the API context
    api_context = ApiContext.restore('bunq-production.conf')
    api_context.ensure_session_active()
    api_context.save('bunq-production.conf')

    BunqContext.load_api_context(api_context)

    # User info
    user = endpoint.User.get().value.get_referenced_object()

    # To get a list we want a pagination object.
    # When making a pagination object yourself you normally only set the 'count'
    # Then you get the url params from it using 'url_params_count_only'
    pagination = Pagination()
    pagination.count = 100

    accounts = []

    all_monetary_account_bank = endpoint.MonetaryAccountBank.list(
        pagination.url_params_count_only).value

    for monetary_account_bank in all_monetary_account_bank:
        if monetary_account_bank.status == "ACTIVE":
            accounts.append(monetary_account_bank)

    all_monetary_account_savings = endpoint.MonetaryAccountSavings.list(
        pagination.url_params_count_only).value

    for monetary_account_savings in all_monetary_account_savings:
        if monetary_account_savings.status == "ACTIVE":
            accounts.append(monetary_account_savings)

    # Reload where we where last time.
    try:
        with open("seen.pickle", "rb") as fp:
            seen = pickle.load(fp)
    except Exception:
        seen = set()
    # We will keep a list of transactions that are already processed in this set.
    # The transactions will contain:
    #  - A set of the two possible roundings of the datestamp
    #  - The ammount of money in absolute value
    #  - The description
    #  - A set containing the two accounts involved
    # The goal here is that this representation is the same for two accounts when shifting money arround.

    for a in accounts:
        aid = a.id_
        # keep track of where we are
        print(a.description)

        for p in iter_payments(aid):
            # python can handle the dates we get back
            date = dateparse.parse(p.created)

            #round to the second to get a (sort of) unique, but not to precise timestamp
            since_epoch = int(unix_time(date))

            row = [
                p.created, p.amount.value,
                p.description.replace("\r", "").replace("\n", " "),
                p.alias.label_monetary_account.iban,
                p.counterparty_alias.label_monetary_account.iban
            ]

            # frozenset can be used to hash a set, so the order does not matter.
            summary = (
                unique_float(
                    since_epoch),  #take both so there is norounding problem
                abs(float(p.amount.value)),
                p.description,
                frozenset([
                    p.alias.label_monetary_account.iban,
                    p.counterparty_alias.label_monetary_account.iban
                ]))

            # Still in range
            if date >= dt:
                if summary in seen:
                    continue
                else:
                    seen.add(summary)
                    yield (row)
            else:
                break

    with open("seen.pickle", "wb") as fp:
        pickle.dump(seen, fp)
コード例 #7
0
from os.path import isfile
import argparse

from bunq.sdk.context import ApiContext
from bunq.sdk.context import ApiEnvironmentType

parser = argparse.ArgumentParser("Generate a Bunq API context.")
parser.add_argument("api_key",
                    metavar="KEY",
                    help="An API key as acquired from the Bunq app.")
parser.add_argument("device_name", metavar="NAME", help="A device name.")
parser.add_argument("output_filename",
                    metavar="FILE",
                    help="A destination for the context.")

args = parser.parse_args()

ApiContext(ApiEnvironmentType.PRODUCTION, args.api_key,
           args.device_name).save(args.output_filename)

api_context = ApiContext.restore(args.output_filename)
api_context.ensure_session_active()
api_context.save()