- #|
-
- src/models/ygoprodeck-cardinfo.lisp
-
- Version 2 JSON Downloader
-
- The idea behind this code is you'll be able to one click button download and update the db:
-
- (cardinfo-update-and-cleanup t)
-
- TODO Use INFERIOR-SHELL
-
- |#
-
- (in-package #:cl-deck-builder2.models.ygoprodeck.cardinfo)
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Constants
- (defparameter +ygoprodeck-api-uri+ "https://db.ygoprodeck.com/api/v7/cardinfo.php")
- (defparameter +ygoprodeck-api-uri-misc+ :|misc|)
- (defparameter +ygoprodeck-api-uri-tcgplayer-data+ :|tcgplayer_data|)
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Specials
- (defparameter *cardinfo* nil
- "The current CARDINFO object.")
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Class Definitions
- (defclass cardinfo ()
- ((input :initarg :input)
- (output :initarg :output)))
-
- (defclass cardinfo-php (cardinfo)
- ()
- (:default-initargs
- :input +ygoprodeck-api-uri+
- :output #P"/tmp/cardinfo.php"
- :tcgplayer-data "yes"
- :misc "yes"))
-
- (defclass cardinfo-json (cardinfo)
- ()
- (:default-initargs
- :input #P"/tmp/cardinfo.php"
- :output #P"/tmp/cardinfo.json"))
-
- ;; Extract the card_images image_url from the cardinfo.json
- ;;
- ;; jq '.[].card_images[].image_url' < /tmp/cardinfo.json
- (defclass cardinfo-list (cardinfo)
- ()
- (:default-initargs
- :input #P"/tmp/cardinfo.json"
- :output #P"/tmp/cardinfo.list"))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Generics
- (defgeneric cardinfo-cleanup (obj))
-
- (defgeneric cardinfo-convert (from to &optional force))
-
- (defgeneric cardinfo-download (obj &optional force))
-
- (defgeneric cardinfo-input (obj)
- (:method ((obj cardinfo))
- (let ((slot-value (slot-value obj 'input)))
- (typecase slot-value
- (pathname (namestring slot-value))
- (t slot-value)))))
-
- (defgeneric cardinfo-output (obj)
- (:method ((obj cardinfo))
- (let ((slot-value (slot-value obj 'output)))
- (typecase slot-value
- (pathname (namestring slot-value))
- (t slot-value)))))
-
- (defgeneric (setf cardinfo-input) (new-value obj)
- (:method (new-value (obj cardinfo))
- (setf (slot-value obj 'input) new-value)))
-
- (defgeneric (setf cardinfo-output) (new-value obj)
- (:method (new-value (obj cardinfo))
- (setf (slot-value obj 'output) new-value)))
-
- (defgeneric cardinfo-input-exists-p (obj)
- (:method ((obj cardinfo))
- (probe-file (cardinfo-output obj))))
-
- (defgeneric cardinfo-output-exists-p (obj)
- (:method ((obj cardinfo))
- (probe-file (cardinfo-output obj))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Methods
- (defmethod initialize-instance :after ((obj cardinfo-php) &rest initargs &key misc tcgplayer-data &allow-other-keys)
- (declare (ignore initargs))
- (let ((params '()))
- (when misc (setf (getf params +ygoprodeck-api-uri-misc+) misc))
- (when tcgplayer-data (setf (getf params +ygoprodeck-api-uri-tcgplayer-data+) tcgplayer-data))
- (when params
- (setf (cardinfo-input obj)
- (caveman2.helper::add-query-parameters
- (cardinfo-input obj) params))))
- obj)
-
- (defmethod cardinfo-cleanup ((obj cardinfo))
- (v:info :ygoprodeck.json "CARDINFO-CLEANUP: ~a" obj)
- (uiop:delete-file-if-exists (cardinfo-output obj)))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; TODO This could probably be replaced with CL-JSON processor.
- (defun cardinfo-run-program (command from to &optional force)
- (let* ((from-output (cardinfo-output from))
- (from-output-exists-p (probe-file from-output))
- ;; TO-INPUT is the same as FROM-OUTPUT
- (to-input (cardinfo-input to))
- (to-output (cardinfo-output to))
- (to-output-exists-p (probe-file to-output)))
- (if (and (string= from-output to-input)
- from-output-exists-p
- (or force
- (not to-output-exists-p)))
- (let ((command (format nil command from-output to-output)))
- (v:info :ygoprodeck.cardinfo "Running command: \"~a\"" command)
- (if (uiop:run-program command :output '(:string :stripped t))
- (cardinfo-output-exists-p to)))
- (v:info :ygoprodeck.cardinfo "Detected existing file: \"~a\"" to-output))))
-
- (defmethod cardinfo-convert ((from cardinfo-php) (to cardinfo-json) &optional force)
- (cardinfo-run-program "jq '.data' < \"~a\" > \"~a\"" from to force))
-
- (defmethod cardinfo-convert ((from cardinfo-json) (to cardinfo-list) &optional force)
- (cardinfo-run-program "jq '.[].card_images[].image_url' < \"~a\" > \"~a\"" from to force))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (defmethod cardinfo-download ((obj cardinfo) &optional force)
- (v:info :ygoprodeck.json "CARDINFO-DOWNLOAD: ~a"
- (cardinfo-input obj))
- (let* ((input (cardinfo-input obj))
- (output (cardinfo-output obj))
- (output-exists-p (probe-file output)))
- (if (or force
- (not output-exists-p))
- (trivial-download:download input output)
- (cardinfo-output-exists-p obj))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (defun cardinfo-update-and-cleanup (&optional cleanup)
- (let ((cardinfo-php (make-instance 'cardinfo-php))
- (cardinfo-json (make-instance 'cardinfo-json))
- (cardinfo-list (make-instance 'cardinfo-list)))
- (cardinfo-download cardinfo-php)
- (cardinfo-convert cardinfo-php cardinfo-json)
- (cardinfo-convert cardinfo-json cardinfo-list)
- (when cleanup
- (mapcar #'cardinfo-cleanup (list cardinfo-php cardinfo-json cardinfo-list)))))
|