arcology-elisp/arcology-checkin.el

172 lines
7.5 KiB
EmacsLisp

;;; arcology-checkin.el --- Checkin support for arcology
;; Copyright (C) 2016 Ryan Rix
;; Author: Ryan Rix <ryan@whatthefuck.computer>
;; Version: 0.1
;; Package-Requires: ((json "0.1") (org "8.0"))
;; Keywords: web
;; URL: http://notes.whatthefuck.computer/
;;; Commentary:
;; This package generates a small blog from org-mode files, leveraging Microformats to provide
;; semantic information about the posts; you can use this information to automate sharing,
;; linkbacks, embedding images in 3rd party silso, and more; see http://indiewebcamp.com and
;; http://microformats.org for more information.
;; This package can be used by configuring the various variables and then calling [`arcology']
;; which will publish the blog index, an RSS feed and URLs for each entry. You can then have Brid.gy
;; automatically syndicate the content to silos by calling [`arcology-syndicate-entry-at-point'].
;; From Wikipedia:
;; Arcology, a portmanteau of "architecture" and "ecology", is a vision of architectural design
;; principles for very densely populated habitats. The concept has been primarily popularized, and
;; the term itself coined, by architect Paolo Soleri. It also appears in science fiction. These
;; structures have been largely hypothetical insofar as no 'arcology' envisioned by Soleri himself
;; has yet been completed, but he posited that a completed arcology would provide space for a
;; variety of residential, commercial, and agricultural facilities while minimizing individual human
;; environmental impact. Arcologies are often portrayed in sci-fi as self-contained or economically
;; self-sufficient.
;; Arcology aims to be a self-sufficient blogging platform, where you can leverage the work that
;; IndieWeb actors have done to build a self-sufficient site with the full support of "social media"
;; type offerings like comments, reposts, checkins, all running under your own domain and backed by
;; plain text that you can control yourself or generate using simple scripts or Memacs
;;; Code:
;;;###autoload
(defgroup arcology-checkin nil
"Checkin support for Arcology."
:group 'arcology)
;;;###autoload
(defcustom arcology-checkin-foursquare-client-id ""
"Foursquare app client ID.
Register an app at https://foursquare.com/developers/apps."
:group 'arcology-checkin)
;;;###autoload
(defcustom arcology-checkin-foursquare-client-secret ""
"Foursquare app client secret.
Register an app at https://foursquare.com/developers/apps."
:group 'arcology-checkin)
;;;###autoload
(defcustom arcology-checkin-cache-location "~/.emacs.d/arcology-venue-data/"
"Directory to put arcology venue cache."
:group 'arcology-checkin)
;;;###autoload
(defcustom arcology-checkin-template-file "/home/rrix/Projects/notes/templates/default.html"
"Template file to use for notes"
:group 'arcology-checkin)
(defun arcology-add-checkin-content (entry)
"Generate checkin venue information, along with checkin note."
(let ((properties (plist-get entry :properties)))
(when (not (arcology-alist-get "CHECKIN-VENUE-ID" properties))
(with-current-buffer (plist-get entry :buffer)
(display-buffer (current-buffer))
(goto-char (plist-get entry :point))
(call-interactively 'arcology-checkin-get-venue-id)))
(let* ((checkin-venue-id (arcology-alist-get "CHECKIN-VENUE-ID" properties))
(venue (arcology-checkin-venue-cached checkin-venue-id))
(image-str (arcology-add-image-content entry)))
(with-temp-buffer
;; Render venue information
(insert image-str)
(insert "<div class=\"p-location h-card arcology-venue\">"
"Posted at "
"<a class=\"u-url p-name\" href=\"https://foursquare.com/v/" (arcology-alist-get 'id venue) "\">"
(arcology-alist-get 'name venue)
"</a> on "
"<span class=\"p-street-address\">"
(or (arcology-alist-get 'address (arcology-alist-get 'location venue)) "")
"</span> in "
"<span class=\"p-locality\">"
(or (arcology-alist-get 'city (arcology-alist-get 'location venue)) "")
"</span>, "
"<span class=\"p-region\">"
(or (arcology-alist-get 'state (arcology-alist-get 'location venue)) "")
"</span> "
"<span class=\"p-country-name\">"
(or (arcology-alist-get 'country (arcology-alist-get 'location venue)) "")
"</span>"
"</div>")
(buffer-string)))))
(defun arcology-checkin-venue-cached (id)
(let ((filename (concat arcology-checkin-cache-location
"/" id ".el")))
(if (file-exists-p filename)
(with-current-buffer (find-file-noselect filename)
(goto-char (point-min))
(let ((v (read (current-buffer))))
(kill-buffer)
v))
(arcology-checkin-cache-venue id))))
;;;###autoload
(defun arcology-checkin-get-venue-id (venue-name location)
"Interactively read checkin information to get venue ID."
(interactive "MWhat is the venue name? \nMWhat city are you in? ")
(let ((req (request "https://api.foursquare.com/v2/venues/search"
:type "GET"
:params `(("client_id" . ,arcology-checkin-foursquare-client-id)
("client_secret" . ,arcology-checkin-foursquare-client-secret)
("query" . ,venue-name)
("near" . ,location)
("v" . "20140806")
("m" . "foursquare"))
:parser 'json-read
:sync t)))
(let* ((venue (elt (arcology-alist-get 'venues (cdar (request-response-data req))) 0))
(venue-id (arcology-alist-get 'id venue)))
(arcology-checkin-write-cache-venue venue-id venue)
(org-set-property "CHECKIN-VENUE-ID"
venue-id)
venue-id)))
(defun arcology-checkin-write-cache-venue (id data)
"Cache a checkin search result"
(unless (file-exists-p arcology-checkin-cache-location)
(make-directory arcology-checkin-cache-location))
(with-current-buffer (find-file-noselect
(concat arcology-checkin-cache-location
"/" id ".el"))
(erase-buffer)
(print data (current-buffer))
(save-buffer)
(kill-buffer)))
(defun arcology-checkin-cache-venue (id)
"Hit the foursquare API for an venue's information.
Used if the ID is already known, but the venue is uncached."
(let ((req (request (format "https://api.foursquare.com/v2/venues/%s" id)
:type "GET"
:params `(("client_id" . ,arcology-checkin-foursquare-client-id)
("client_secret" . ,arcology-checkin-foursquare-client-secret)
("v" . "20140806")
("m" . "foursquare"))
:parser 'json-read
:sync t)))
(let* ((response (arcology-alist-get 'response (request-response-data req)))
(venue (arcology-alist-get 'venue response))
(venue-id (arcology-alist-get 'id venue)))
(arcology-checkin-write-cache-venue id venue)
venue)))
(def-arcology-entry-generator checkin
(lambda (entry) (concat
(arcology-get-default-content entry)
(arcology-add-checkin-content entry))))
(provide 'arcology-checkin)
;; arcology-checkin.el ends here.