Browse Source

Added downloads, integrating with fin-api

Simon Watson 1 year ago
parent
commit
f494fddce8
1 changed files with 52 additions and 1 deletions
  1. 52 1
      fin-lisp.lisp

+ 52 - 1
fin-lisp.lisp

@@ -3,10 +3,12 @@
 (ql:quickload "cl-ppcre")
 (ql:quickload "unix-opts")
 (ql:quickload "ironclad")
+(ql:quickload "dexador")
 
 ;;; Features
 ;;; - Import records from old .txt format
 ;;;   - Removed as I'll never use it again
+;;;     - Added in again to retest some things
 ;;; - Interactive prompt to manage expenses
 ;;; - Generic expense handling
 ;;; TODO
@@ -24,6 +26,9 @@
 ;;; where the key is the month stamp, eg 20210701
 ;;; and the value is the monthly expenses hash
 (defvar *records* (make-hash-table :test 'equalp))
+(defvar *api-config-path* "./auth.json")
+(defvar *api-url* NIL)
+(defvar *api-key* NIL)
 
 (defun file-test (filename)
   (if (probe-file filename) filename (print "Couldn't find filename")))
@@ -73,6 +78,9 @@
 ;;; See: https://www.cliki.net/Ironclad
 
 ;;; Return cipher when provided key
+;;; Currently, this is 'insecure' as we are using a string
+;;; coerced into a byte array as the key, aka a non-random secret.
+;;; Should use twofish
 (defun get-cipher (key)
   (ironclad:make-cipher
    :blowfish
@@ -101,6 +109,34 @@
 ;;; End Encryption Stuff ;;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
+;;; Can only be called from the REPL,
+;;; used for importing according to the old schema
+(defun import-records (filename)
+  (let ((old-file-lines
+	  (with-open-file (stream filename)
+	    (loop for line = (read-line stream nil)
+		  while line
+		  collect line)))
+	(mre (ppcre:create-scanner "^(.*)[0-9]{4}$"))
+	(ere (ppcre:create-scanner "^([A-Z].*)\ -\ \\\$([0-9]{1,4}) - PAID"))
+	(cur-mon)
+	(cur-exp))
+    (loop for line in old-file-lines
+	  do (progn
+	       (if (ppcre:scan mre line) (setf cur-mon line))
+	       (if (ppcre:scan ere line)
+		   (progn
+		     (setf cur-exp (ppcre:register-groups-bind (first second) (ere line) :sharedp t (list first second)))
+		     (print cur-exp)
+		     (if (gethash cur-mon *records*)
+			 (let ((innerhash (gethash cur-mon *records*)))
+			   (setf (gethash (first cur-exp) innerhash) (second cur-exp))))
+		     (if (not (gethash cur-mon *records*))
+			 (progn
+			   (add-month cur-mon)
+			   (let ((innerhash (gethash cur-mon *records*)))
+			     (setf (gethash (first cur-exp) innerhash) (second cur-exp)))))))))))
+
 (defun reset-records ()
   (setf *records* (make-hash-table :test 'equal)))
   
@@ -145,6 +181,7 @@
   (let ((record-key-list (loop for key being the hash-keys of *records* collect key)))
     (dolist (month-key record-key-list) (dump-month month-key))))
 
+;;; Serialization and communicating with the web API
 (defun serialize-records (key filename)
   (with-open-file (stream filename
 			  :direction :output
@@ -157,6 +194,21 @@
 (defun deserialize-records (key filename)
   (setf *records* (yason:parse (decrypt-records key filename))))
 
+(defun parse-api-config (path)
+  (let ((api-config-hash (yason:parse (uiop:read-file-string path)))
+	(ret-tuple '()))
+    (push (gethash "token" api-config-hash) ret-tuple)
+    (push (gethash "url" api-config-hash) ret-tuple)
+    ret-tuple))
+
+(defun download-records ()
+  (let* ((api-config (parse-api-config *api-config-path*))
+	(dl-records (yason:parse (dex:get (concatenate 'string (first api-config) "download")
+					  :headers (list (cons "X-Token" (second api-config)))))))
+    dl-records))
+
+(defun upload-records (records-file))
+
 (defmacro generic-handler (form error-string)
   `(handler-case ,form
     (error (e)
@@ -215,7 +267,6 @@
     (when-option (matches :help)
       (display-help))
     (when-option (matches :print-month)
-      
     (when-option (matches :interactive-mode)
       (progn
 	(interactive-mode)