The chocolate ration is being increased to 25 grammes per week.

Nintendo DS tracker notifier

The following script notifies me via a text message when either a Cobalt Blue or Crimson Nintendo DS Lite are available. It uses dstracker.com‘s XML feed.

Required software: Allegro CL 8.1 Express on Linux (though it could be adapted to Windows fairly easily by not trying to detach-from-terminal).

#! /usr/local/bin/mlisp -#C

;; Nintendo DS Lite tracker notifier.

(in-package :user)

(eval-when (compile eval load)
(require :osi)
(use-package :excl.osi)
(require :aserve)
(use-package :net.aserve.client)
(require :sax)
(use-package :net.xml.dom)
(require :smtp)
(use-package :net.post-office))

(defparameter *dstracker-url* "http://dstracker.com/rss.xml")
(defparameter *email* "...@txt.att.net")
(defparameter *re*
;; I only want to be notified of the Crimson and Cobalt versions:

(defun read-feed (url)
(logit "reading feed from ~a" url)
(multiple-value-bind (content code headers)
(do-http-request url)
(declare (ignore headers))
(if* (not (eq 200 code))
then (error "Accessing url ~s gave http response code ~s" url code))

(defun notify-user (to body ht)
(when (not (gethash body ht))
(setf (gethash body ht) t)
(logit "notify ~a" to)
(send-smtp "localhost" "dstracker" to body)))

(defun parse-feed-and-notify (xml ht)
(let* ((doc (parse-to-dom xml))
(root (dom-document-element doc))
(items (dom-list-elements-by-tag-name root "item")))
(dolist (item items)
(let* ((title (dom-list-elements-by-tag-name item "title"))
(text (dom-child-node-list (car title)))
(data (dom-data (car text))))
(when (match-re *re* data :case-fold t)
(notify-user *email* data ht))))))

(defun logit (format-string &rest format-arguments)
(format t "~@/locale-format-time/" (get-universal-time))
(apply #'format t format-string format-arguments)
(format t "~&"))

(defun doit ()
(let ((ht (make-hash-table :size 101 :test #'equalp)))
(parse-feed-and-notify (read-feed *dstracker-url*) ht)
(sleep #.(* 60 10)))))

(system:with-command-line-arguments ("l:" logfile)
(declare (ignore rest))
(when (not logfile) (error "Must supply a log file via -l argument."))
(with-open-file (s logfile :direction :output :if-exists :always-append
:if-does-not-exist :create)
(if* (= (excl.osi:fork) 0)
then ;; child
(excl.osi:detach-from-terminal :output-stream s
:error-output-stream s)
(logit "starting up")
else (exit 0 :quiet t))))

Image courtesy of imageshack.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: