Skip to content

Instantly share code, notes, and snippets.

@tbarbugli
Created October 14, 2015 21:23
Show Gist options
  • Select an option

  • Save tbarbugli/0438bb2cb4b4bae082d5 to your computer and use it in GitHub Desktop.

Select an option

Save tbarbugli/0438bb2cb4b4bae082d5 to your computer and use it in GitHub Desktop.
Steram Cloujure API client
(ns fub.timeline.stream
(:require [clojure.string :as strs]
[clojure.data.codec.base64 :as b64]
[full.core.sugar :refer :all]
[full.async :refer :all]
[full.core.config :refer [opt]]
[full.http.client :as http]
[full.core.log :as log]
[full.time :refer [dt<-iso-ts dt->iso-ts]]
[full.json :refer [write-json]])
(:import (javax.crypto Mac)
(javax.crypto.spec SecretKeySpec)
(java.security MessageDigest)))
(def api-key (opt [:fulcrum :stream :api-key]))
(def api-secret (opt [:fulcrum :stream :api-secret]))
(def region (opt [:fulcrum :stream :region]))
(def api-url (delay (str "https://"
(when-let [region @region]
(str region "-"))
"api.getstream.io/api/v1.0")))
(def HMAC_SHA1 "HmacSHA1")
(def SHA1 "SHA-1")
(def UTF8 "UTF-8")
(defn- auth-signature
([feed-slug user-id] (auth-signature feed-slug user-id @api-secret))
([feed-slug user-id api-secret]
(let [signing-key (-> (MessageDigest/getInstance SHA1)
(.digest (.getBytes api-secret UTF8))
(SecretKeySpec. HMAC_SHA1))
mac (Mac/getInstance HMAC_SHA1)]
(.init mac signing-key)
(-> (str feed-slug user-id)
(.getBytes UTF8)
(->> (.doFinal mac))
(b64/encode)
(String.)
(.replace \+ \-)
(.replace \/ \_)
(strs/replace #"^=+" "")
(strs/replace #"=+$" "")))))
(defn- assoc-auth-headers [headers feed-slug user-id]
(let [headers (or headers {})]
(assoc headers "Authorization" (str feed-slug user-id " "
(auth-signature feed-slug user-id)))))
(defn req> [{:keys [feed-slug user-id headers params body] :as req}]
(let [req (assoc req :base-url @api-url
:headers (-> headers
(assoc-auth-headers feed-slug user-id)
(cond-> body (assoc "Content-Type" "application/json")))
:params (assoc (or params {}) "api_key" @api-key)
:body (when body (write-json body :json-key-fn name)))]
(http/req> req)))
(defn add-to-signature [to]
(when to
(->> to
(map (fn [feed-id]
(let [[feed-slug user-id] (strs/split feed-id #":")]
(if (and feed-slug user-id)
(str feed-id " " (auth-signature feed-slug user-id))
(log/error "Invalid feed-id" feed-id "(ignoring)")))))
(filter identity))))
(defn serialize-activity [activity]
(-> activity
(update-in [:time] dt->iso-ts)
(update-in [:to] add-to-signature)))
(defn deserialize-activity [activity]
(-> activity
(update-in [:time] #(some-> % (str "Z") dt<-iso-ts))))
(defn feed>
[feed-slug user-id & {:keys [limit id-gte id-gt id-lte id-lt offset]}]
(go-try
(->> (req> {:resource (str "feed/" feed-slug "/" user-id "/")
:params (?hash-map "limit" limit
"id_gte" id-gte
"id_gt" id-gt
"id_lte" id-lte
"id_lt" id-lt
"offset" offset)
:feed-slug feed-slug
:user-id user-id})
<?
:results
(map deserialize-activity))))
(defn create-activities>
[feed-slug user-id activities]
(go-try
(->> (req> {:resource (str "feed/" feed-slug "/" user-id "/")
:method :post
:body {:activities (map serialize-activity activities)}
:feed-slug feed-slug
:user-id user-id})
<?
:activities
(map deserialize-activity))))
(defn delete-activity> [feed-slug user-id activity-id]
(req> {:resource (str "feed/" feed-slug "/" user-id "/" activity-id "/")
:method :delete
:feed-slug feed-slug
:user-id user-id}))
(defn following> [feed-slug user-id]
(go-try
(->> (req> {:resource (str "feed/" feed-slug "/" user-id "/following/")
:method :get
:feed-slug feed-slug
:user-id user-id})
<?
:results)))
(defn follow> [feed-slug user-id target-feed-slug target-user-id]
(req> {:resource (str "feed/" feed-slug "/" user-id "/following/")
:method :post
:feed-slug feed-slug
:user-id user-id
:body {:target (str target-feed-slug ":" target-user-id)}}))
(defn unfollow> [feed-slug user-id target-feed-slug target-user-id]
(req> {:resource (str "feed/" feed-slug "/" user-id "/following/"
target-feed-slug ":" target-user-id "/")
:method :delete
:feed-slug feed-slug
:user-id user-id}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment