Giter VIP home page Giter VIP logo

teller-cli's Introduction

teller-cli Build Status

Banking for your command line

This tool provides useful ways of interrogating your bank through your command line, and is not merely meant to be a one-to-one match with underlying APIs.

It uses Teller behind-the-scenes to interact with your UK bank, so you will need to have an account there.

๐Ÿ‘† Want an account? @stevegraham can hook you up!

Usage

teller show balance current will show you your current account's balance.

teller --help for more commands.

e.g.

Instructions

Why?

Notifications with terminal-notifier

teller show balance current | terminal-notifier -title "Current Account Balance"

Notifications

Alert when ๐Ÿ’ฐ low

#!/bin/sh

CURRENT_BALANCE=`teller show balance current --hide-currency`;
MIN_BALANCE=1000.00;

if (( $(bc <<< "$CURRENT_BALANCE < $MIN_BALANCE") ))
then
  echo "Your current balance has fallen below ยฃ$MIN_BALANCE" | terminal-notifier -title "๐Ÿ’ฐ Alert" -subtitle "Current Balance is ยฃ$CURRENT_BALANCE";
fi

Alerts

โ˜• How much money do I spend at Nanna's?

> teller list transactions current | grep "NANNA'S"
27   2015-11-12  NANNA'S             -2.70
60   2015-10-28  NANNA'S             -2.40
68   2015-10-26  NANNA'S             -5.40
101  2015-10-09  NANNA'S             -2.70
203  2015-07-17  NANNA'S             -4.60
206  2015-07-16  NANNA'S             -9.90
208  2015-07-16  NANNA'S             -9.30
209  2015-07-16  NANNA'S             -0.10

Hopefully Teller will add support for querying transactions soon.

Am I saving money with a chart ๐Ÿ“ˆ with spark

> teller list balances business --interval=monthly --timeframe=year --output=spark | spark
โ–โ–โ–โ–‚โ–ƒโ–‚โ–ƒโ–„โ–„โ–…โ–†โ–ˆ

Have I spent more money this month than I normally do?

#!/bin/sh

CURRENT_OUTGOING=`teller show outgoing current --hide-currency | sed 's/^-//'`;
OUTGOINGS=`teller list outgoings current --output=spark`;
SUM_OUTGOING=`echo "$OUTGOINGS" | sed 's/ /+/g' | bc -l | sed 's/^-//'`;
COUNT_OUTGOING=`echo "$OUTGOINGS" | wc -w | xargs`;
AVERAGE_OUTGOING=`bc <<< "scale=2; $SUM_OUTGOING / $COUNT_OUTGOING"`;

if (( $(bc <<< "$CURRENT_OUTGOING > $AVERAGE_OUTGOING") ))
then
  DIFFERENCE_OUTGOING=`bc <<< "scale=2; $CURRENT_OUTGOING - $AVERAGE_OUTGOING"`;
  echo "You've spent ยฃ$DIFFERENCE_OUTGOING more than normal." | terminal-notifier -title "๐Ÿ’ฐ Spending Alert" -subtitle "Current Outgoing is ยฃ$CURRENT_OUTGOING";
fi

Keep track of your spending from the OSX Menu Bar with BitBar

Create a track-spending.1h.sh within your plugins directory:

#!/bin/sh
#
# Teller.io Banking via the OSX menu bar
# Requires:
# - a Teller.io account
# - a UK Bank
# - teller-cli: https://github.com/sebinsua/teller-cli#from-release
# - pcregrep: `brew install pcre`
#
# <bitbar.title>teller-track-spending</bitbar.title>
# <bitbar.version>v1.3.1</bitbar.version>
# <bitbar.author>Seb Insua</bitbar.author>
# <bitbar.author.github>sebinsua</bitbar.author.github>
# <bitbar.desc>Track your spending from your menu bar</bitbar.desc>
# <bitbar.image>https://camo.githubusercontent.com/e0215e6736172334f62effff36ff8df1ab38fed1/687474703a2f2f692e696d6775722e636f6d2f627638545a4c652e706e67</bitbar.image>
# <bitbar.dependencies>teller-cli, pcregrep</bitbar.dependencies>
# <bitbar.abouturl>https://github.com/sebinsua/teller-cli</bitbar.abouturl>

export PATH="/usr/local/bin:/usr/bin/:$PATH";

SPENDING_LIMIT='3000.00'; # Change this to a suitable spending limit.

exit_if_zero() {
  RETURN_CODE=$1;
  ERROR_MESSAGE=$2;
  if [ "$ERROR_MESSAGE" = "" ]; then
    ERROR_MESSAGE="Offline";
  fi;
  if [ "$RETURN_CODE" -ne 0 ]; then
    echo "$ERROR_MESSAGE|color=#7e7e7e";
    exit 1;
  fi;
}

# If we're offline we shouldn't output junk in the menu bar.
curl --connect-timeout 5 www.google.com > /dev/null 2> /dev/null;
exit_if_zero $? "Offline";

CURRENT_OUTGOING=$(teller show outgoing current --hide-currency);
exit_if_zero $? "Error";

CURRENT_BALANCE=$(teller show balance current --hide-currency);
exit_if_zero $? "Error";

LAST_TRANSACTION=$(teller list transactions | tail -n 1 | pcregrep -o1 "[0-9]+[ ]+(.*)");
exit_if_zero $? "Error";

if [ "$(echo "$CURRENT_OUTGOING > $SPENDING_LIMIT" | bc)" -ne 0 ]; then
  OVERSPEND=$(echo "scale=2; $CURRENT_OUTGOING - $SPENDING_LIMIT" | bc);
  echo "๐Ÿšจ ยฃ$OVERSPEND OVERSPENT|color=red";
else
  UNDERSPEND=$(echo "scale=2; $SPENDING_LIMIT - $CURRENT_OUTGOING" | bc);
  if [ "$(echo "$UNDERSPEND > ($SPENDING_LIMIT/2)" | bc)" -ne 0 ]; then
    echo "๐Ÿฆ ยฃ$UNDERSPEND remaining|color=green";
  else
    echo "๐Ÿฆ ยฃ$UNDERSPEND remaining|color=#ffbf00";
  fi;
fi;
echo "---";
echo "Current Account: ยฃ$CURRENT_BALANCE";
echo "Current Outgoing: ยฃ$CURRENT_OUTGOING";
echo "Last TX: $LAST_TRANSACTION";

Tracking spending in the OSX Menu Bar

Installation

From release

> curl -L https://github.com/sebinsua/teller-cli/releases/download/v0.0.7/teller > /usr/local/bin/teller && chmod +x /usr/local/bin/teller

From source

First git clone and then:

> cargo build --release && cp ./target/release/teller /usr/local/bin && chmod +x /usr/local/bin/teller

FAQ

Compiling gives openssl/hmac.h not found error

Ensure that both Homebrew and openssl are installed, and then try running brew link --force openssl.

This relates to the following error:

--- stderr
src/openssl_shim.c:1:10: fatal error: 'openssl/hmac.h' file not found
#include <openssl/hmac.h>

If brew complains about not being able to force-link openssl then you could try building like this:

OPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include DEP_OPENSSL_INCLUDE=/usr/local/opt/openssl/include cargo build

teller-cli's People

Contributors

sebinsua avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

teller-cli's Issues

Create `list counterparties` command

list counterparties should list descending the top-N counterparties and their respective cumulative amounts within a timeframe in a table.

For reusability this should be generated from a counterparty to (date, amount) hashmap.

Ideas around common transactions

Detect common transactions

Might be interesting to take a list of transactions and create another list of regular transactions.

  1. Transactions with the same organisation.
  2. Transactions for the same amount.
  3. Transactions that repeat on a specific day every month.
  4. Transactions that repeat on a specific day and month every year.

There has to be some kind of threshold that is passed before considering a transaction common or even regular to stop things like coffee transactions being seen as regular, etc.

In general I expect 1 but not 3 or 4 would mean you were actively re-engaging a service, while 1+3 or 1+4 would mean you were passive and they were re-engaging with you due to a contract stipulating a level of service.

2 is only interesting because it helps us calculate past burn rates and estimate future burn rates. Also the absence of a stable 2 creates variability and risk.

Knowing this would help us:

  • Reduce burn rates.
  • Recommend replacements to transactions (bundling or other similar services.)
  • Get some understanding of the trade-offs between spending ยฃ400 on a pair of gucci loafers once, and spending an extra ยฃ100 a month at Waitrose.

Further thoughts:

  1. Given a list of transactions from a normalised Counterparty group them by behaviour and tag each group with regular-amount, variable-amount, sporadic-interval, regular-interval. These are patterns. Sum each pattern. Remove transaction groups that are below thresholds of utility. (Although the data would be fascinating, it is probably not worth doing until we have an interesting pictorial/textual representation that will give instant usability.)
  2. Open question about which is more appropriate for a group key at a given point and what do we have access to: Counterparty vs normalised Counterparty vs service/product/utility vs category of service/product/utility

Survival spend

Later on we could create some kind of basic survival spend command that would let you know the amount of money that must always be present in your account for basic living - a total, and a list of transactions that represent the average minimum viable monthly basket. Eventually allowing us to automate current account topups towards this number.

Perhaps there could also be some kind of show transaction next --type=regular command that could tell you the next regular transaction that should be coming out.

Payment commands

  • teller list payment-mechanisms current
  • teller send <amount> [<currency>] --from=<from> --to=<to>

Note: <from> and <to> might be able to contain URIs.

Must be well-supported in Teller before being implemented.

List balances for the last 12 months

In order to support teller list balances business --interval=monthly --only-numbers we need to be able to:

  1. Get the current balance.
  2. Get the last 12 months of transactions.
  3. Get the final balance of each month, including the current month. To do this we need to minus each of the transactions from the current balance cumulatively.
  4. Create a Vec of month_final_balances.
  5. Write this to stdout.

Note: if Teller adds from and to query strings this would be easier

UX changes to `list transactions`

  • By default do not show description. Put it behind a flag.
  • currency should appear after a tab following the amount if --only-numbers is not set.

Design and implement additional commands

  • #4 teller list balances current --interval=monthly --timeframe=year
  • teller list transactions current
  • teller list direct-debits current
  • teller list standing-orders current

  • teller list payment-mechanisms current
  • teller send <amount> [<currency>] --from=<from> --to=<to>

  • teller search transactions current --query=<query>

Worth looking at keen-cli for some ideas, although we are not planning on making generalised analysis tools. Some other features we may need to wait for Teller to support.

Note: <from> and <to> might be able to contain URIs.

Search transactions command

  • teller search transactions current --query=<query>

Must be well-supported in Teller before being implemented.

Implement `show outgoing` and `show incoming`

  • Implement show outgoing and show incoming.
  • Create script that takes the average of 12 months of outgoing and checks to see whether the current outgoing is higher or lower than this (and the difference between them) before notifying you of this. Place this in the README.md as an example of a script that would give you an idea of whether you are spending more than is normal.

Tests

Write unit tests. Will potentially need yup-hyper-mock to help test the client, and to write Fs mocks for testing config.

Before I can finish writing the tests I need to refactor a few hinderances to this in the code.

  • get_transactions needs to a receive a from_date and to_date which are computed within the commands from an injected current_time.
  • In order to alter the server responses when testing each of the commands we will need to be able to inject TellerClients in.
  • Do not test main.
  • inquirer/ask:
    • can I instantiate a Question?
    • can I instantiate an Answer?
    • ask_question:
    • ask_questions:
      • Given a list of questions, only return an answer if one was typed in when prompted.
  • config (see: http://doc.rust-lang.org/std/io/struct.Cursor.html#examples):
    • get_config_path returns the correct path.
    • get_config_file return an Option<File> that is None if not found, and a file otherwise. (NOTE: Closing as not possible to test yet.)
    • get_config_file_to_write return an Result<File, StdIoError> that panics if permission is denied, and the result otherwise. (NOTE: Closing as not possible to test yet.)
    • read_config should return a Result<Config, ConfigError> and write_config a Result<(), ConfigError>.
  • cli/parse:
    • instantiate a CliArgs and then get_command_type with it to return a CommandType.
  • api:
    • api/client:
      • instantiate a TellerClient, Account and Transaction.
      • get_account returns an Account.
      • get_accounts returns a Vec<Account>.
      • get_transactions returns a Vec<Transaction>. Unable to test the timeframe thing easily, so ignore for now.
    • api/inform:
      • instantiate some Money.
      • get_account_balance should return some valid Money.
      • get_aggregates test that get_balances, get_incomings and get_outgoings return monthly absolute values with a currency from the current Account.
      • get_counterparties should return the grouped counterparties outgoing amounts for a particular timeframe.
      • get_incoming should return the Money of the sum of the positive transactions this month.
      • get_outgoing should return the Money of the absolute sum of the negative transactions this month.
      • get_transactions_with_currency should return a valid TransactionsWithCurrrency.

These tests will no longer be done as (1) testing exit codes is not that useful, and (2) perfect representation is not as important as actual computation (make more sense to see it with eyes, than to test spacing with code, etc.)

  • command for each test its represent_ and whether it can return 0 or 1 on network success/failure:
    • initialise.
    • list_accounts.
    • list_balances.
    • list_counterparties.
    • list_incomings.
    • list_outgoings.
    • list_transactions.
    • show_balance.
    • show_incoming.
    • show_outgoing.
    • show_usage.

Clean up the Docopt

  • write [--all --long --human-readable] rather than [--all] [--long] [--human-readable].

UX changes to `list balances`

As well as #8, we need some vanity changes to list balances:

  • We should support timeframes of 3 months and 6 months.
  • Reformat to:
              mon-year       mon-year         mon-year           today
balance (GDP) 23.00          56.00            100.00             34.00
  • --hide-currency should be renamed here as we're using it for a different purpose. Use --output=spark instead.
  • Emit an error message if a different interval from 'monthly' is used. Not supported yet.

Refactor

Take a read of this well-written rust code.

  • Refactor 'client':
    • Create a struct that receives an authToken on instantiation and implements basic methods to fetch data - each of these should use some kind of underlying auth_request method. This is instead of everything receiving &Config (a class that belongs to another module). Move to a separate crate teller_api.
    • The remaining non-HTTP parts of 'client' should perhaps be renamed to 'inform' and receive the data from the API instead of creating it (the information that is applied, does not belong to the client).
  • Refactor 'inquirer':
    • Into a module directory.
  • Refactor 'main':
    • structs and impl Decodables should remain where they are as are command definition related.
    • pick_command should be simpler:
      • Only destructure args to get out what you need to match. 'Additional destructuring](http://rustbyexample.com/flow_control/match/destructuring/destructure_structures.html) should happen before the underlying command is called.
      • Only get_config once, if it is successful then pass the &config onto the commands, otherwise configure_cli. get_config should not be concerned with execution of configure_cli itself. This will mean you will attempt to detect whether cmd_init was picked first, separately to the rest of the other commands prior to get_config being executed.
      • get_config should belong to the 'config' module.
    • init_config should become ask_questions_for_config. Behind the scenes it should use inquirer::ask_questions and some kind of find_answers* function to get the answers out for the config.
    • Commands should be moved into a module 'command'. This includes configure_cli, list_accounts, show_balance, list_transactions, etc.
    • Table writing and other response writing should live in 'represent'. This includes get_account_alias_for_id, represent_list_accounts, represent_show_balance, represent_list_transactions, represent_list_amounts, represent_list_balances, represent_list_outgoings, represent_list_incomings, etc.
  • Carefully remove many of the unwrap statements and clean up many of the deeply-nested matches in the usual ways (separate functions, early returns, let expected_value = match thing { ... }.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.