Last active
August 29, 2015 14:23
-
-
Save nfunato/9ee602523937477008e5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;;; CAUTION: this code is not fully tested! | |
| (ql:quickload | |
| ;; FIXME: use lquery rather than plump if preferable | |
| '( | |
| :drakma ; a full-featured common lisp http client | |
| :plump ; a parser for HTML/XML like document | |
| :clss ; a DOM traversal engine based on CSS selectors | |
| :cl-redis ; a client library for Redis database, an advanced K/V store | |
| ;; :chirp ; a twitter client library for common lisp | |
| ) | |
| :silent t) | |
| ;;; environmental I/F | |
| (defun get-slack-user-token () | |
| (asdf::getenv "SLACK_TOKEN")) | |
| ;;; drakma I/F | |
| (defvar *hbm-get-url* "http://b.hatena.ne.jp/nisemono_san/bookmark") | |
| (defvar *slack-post-url* "https://slack.com/api/chat.postMessage") | |
| (defmacro with-http-error-trap ((msg) &body body) | |
| (let ((ans (gensym)) (stat (gensym)) (hdr (gensym))) | |
| `(multiple-value-bind (,ans ,stat ,hdr) (progn ,@body) | |
| (declare (ignorable ,hdr)) | |
| (unless (<= 200 ,stat 299) (error ,msg)) | |
| ,ans))) | |
| (defun hbm-get () | |
| (with-http-error-trap ("hatena-bookmark-get") | |
| (drakma:http-request *hbm-get-url*))) | |
| (defun slack-post (channel token text) | |
| (with-http-error-trap ("slack-post") | |
| (drakma:http-request *slack-post-url* | |
| :method :post | |
| :parameters `(("token" . ,token) | |
| ("channel" . ,channel) | |
| ("text" . ,text) | |
| ("as_user" . "true"))))) | |
| ;;; (get-latest-hatena-bookmark) -- using plump and clss | |
| (defun get-bookmark-block () | |
| (clss:select ".entry-block" (plump:parse (hbm-get)))) | |
| (defun bookmark-elem-p (elem) | |
| (some (lambda (tag) (string= "@" (plump:text tag))) | |
| (clss:select "a.user-tag" elem))) | |
| (defun bookmark-link (elem) | |
| (plump:attribute (elt (clss:select ".entry-title a.entry-link" elem) 0) | |
| "href")) | |
| (defun get-latest-hatena-bookmark () | |
| (let ((bme (find-if #'bookmark-elem-p (get-bookmark-block)))) | |
| (if bme | |
| (bookmark-link bme)))) | |
| ;;; (hatena->slack) -- working with redis | |
| (defun hatena->slack (&aux (tok (get-slack-user-token))) | |
| (redis:with-connection () ; use default connection "127.0.0.1" | |
| (format t "SLACK TOKEN Settings: ~A ~%" tok) | |
| (let ((lu (red:get :latest-url-redis)) | |
| (hb (get-latest-hatena-bookmark))) | |
| (when hb | |
| (format t "Previous URL: ~A ~%" lu) | |
| (format t "Get URL: ~A ~%" hb) | |
| (when (string/= lu hb) | |
| (slack-post "#random" tok hb) | |
| (red:set :latest-url-redis hb)))))) | |
| (defun main () | |
| (format t "Start.~%") | |
| (hatena->slack) | |
| (format t "Done.~%")) | |
| #+:script-top-level ; don't know whether or not such feature exists! | |
| (main) | |
| #| | |
| ;;; the original -- http://bugrammer.hateblo.jp/entry/2015/06/20/103000 | |
| (let ((*standard-output* (make-broadcast-stream))) | |
| (ql:quickload :cl-redis) | |
| (ql:quickload :drakma) | |
| (ql:quickload :plump) | |
| (ql:quickload :clss) | |
| (ql:quickload :chirp)) | |
| (redis:connect :host "127.0.0.1") | |
| (defvar *user-token* (ccl::getenv "SLACK_TOKEN")) | |
| (defvar *latest-url-redis* :latest-bookmark-post) | |
| (defun post-message (channel text token) | |
| (drakma:http-request "https://slack.com/api/chat.postMessage" | |
| :method :post | |
| :parameters `(("token" . ,token) | |
| ("channel" . ,channel) | |
| ("text" . ,text) | |
| ("as_user" . "true")))) | |
| (defun random-> (text) | |
| (post-message "#random" text *user-token*)) | |
| (defun hatena-request () | |
| (plump:parse | |
| (drakma:http-request "http://b.hatena.ne.jp/nisemono_san/bookmark"))) | |
| (defun hatena-bookmark-block () | |
| (clss:select ".entry-block" (hatena-request))) | |
| (defun post-bookmark-p (element) | |
| (let ((tags (concatenate 'list (clss:select "a.user-tag" element)))) | |
| (and tags | |
| (remove-if-not | |
| (lambda (x) (string= "@" x)) | |
| (mapcar #'plump:text tags))))) | |
| (defun get-bookmark-link (elem) | |
| (plump:attribute (aref (clss:select ".entry-title a.entry-link" elem) 0) | |
| "href")) | |
| (defun latest-hatena-bookmark () | |
| (let ((bookmark-list | |
| (remove-if-not #'post-bookmark-p | |
| (concatenate 'list (hatena-bookmark-block))))) | |
| (when bookmark-list | |
| (get-bookmark-link bookmark-list)))) | |
| (defun hatena->slack () | |
| (let ((hatena-bookmark (latest-hatena-bookmark))) | |
| (format t "Get URL: ~A ~%" hatena-bookmark) | |
| (format t "Previous URL: ~A ~%" (red:get *latest-url-redis*)) | |
| (when (string/= (red:get *latest-url-redis*) hatena-bookmark) | |
| (progn | |
| (random-> hatena-bookmark) | |
| (red:set *latest-url-redis* hatena-bookmark))))) | |
| (format t "Start.~%") | |
| (format t "SLACK TOKEN Settings: ~A ~%" *user-token*) | |
| (hatena->slack) | |
| (format t "Done.~%") | |
| |# |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment