Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add tweeting support

  • Loading branch information...
commit 2eefb0c82c42695da3614bb435eee0750f24dd14 1 parent 30d8867
@apage43 apage43 authored
View
1  .gitignore
@@ -8,3 +8,4 @@ pom.xml
.lein-deps-sum
.lein-failures
.lein-plugins
+marky-config.clj
View
22 README.md
@@ -1,4 +1,4 @@
-# marky is a robotic text generator that leverages Couchbase
+# marky is a nonsensical tweet bot that leverages Couchbase
Looks for a marky-config.clj file in current directory.
@@ -8,17 +8,19 @@ Sample:
{:bucket "default"
:pass ""
:cburl "http://localhost:8091/"
+ :twitter {:app-key "XXXXXXXXX"
+ :app-secret "XXXXXXXXXX"
+ :user-token "XXXXXXXX"
+ :user-secret "XXXXXXXX"}
:jobs
- [{:type :twitter :user "damienkatz" :period 3600}
- {:type :twitter :user "apage43" :period 3600}
- {:type :rss :url "http://damienkatz.net/rss.php" :period 86400}]}
+ [; :period, :after is in seconds, :ttl is in days.
+ {:type :twitter :user "damienkatz" :period 3600 :ttl 60}
+ {:type :twitter :user "apage43" :period 3600 :ttl 60}
+ {:type :send-tweet :period 3600 :after 600}
+ {:type :rss :url "http://damienkatz.net/rss.php" :period 86400 :ttl 60}]}
```
-Run the collector process
+Run the bot process
- $ lein run -m marky.collect
-
-Generate some text
-
- $ lein run -m marky.generate
+ $ lein run -m marky.app
View
7 marky-config.clj
@@ -1,7 +0,0 @@
-{:bucket "default"
- :pass ""
- :cburl "http://localhost:8091/"
- :jobs
- [{:type :twitter :user "damienkatz" :period 3600}
- {:type :twitter :user "apage43" :period 3600}
- {:type :rss :url "http://damienkatz.net/rss.php" :period 86400}]}
View
1  project.clj
@@ -6,6 +6,7 @@
:dependencies [[org.clojure/clojure "1.4.0"]
[org.clojure/data.xml "0.0.6"]
[overtone/at-at "1.0.0"]
+ [twitter-api "0.6.13"]
[crouton "0.1.1"]
[apage43/cbdrawer "0.1.0-SNAPSHOT"]
[clj-http "0.5.6"]])
View
50 src/marky/collect.clj → src/marky/app.clj
@@ -1,4 +1,4 @@
-(ns marky.collect
+(ns marky.app
(:import [javax.xml.transform.stream StreamSource]
[org.jsoup Jsoup])
(:require [overtone.at-at :as at-]
@@ -9,7 +9,10 @@
[cbdrawer.client :as cb]
[cbdrawer.view :as cbv]
[cbdrawer.transcoders :as xcoders]
- [clj-http.client :as http]))
+ [clj-http.client :as http]
+ [twitter.oauth :as tw-oauth]
+ [twitter.api.restful :as tw-rest]
+ [marky.generate :as gen]))
; Collected item
; {:body "body text" :item-id "item id" :source-id "sourceid"}
@@ -36,13 +39,12 @@
(let [sourceid (str "rss=" url)
parsed (xml/parse (StreamSource. url))
entries (filter #(= :entry (:tag %)) (tree-seq :content :content parsed))]
- (map (fn [entry]
+ (for [entry entries]
{:source-id sourceid
:item-id (str sourceid ",title="
(cb-safe (xml-text (first (filter #(= :title (:tag %)) (:content entry))))))
:body (.text (Jsoup/parse
- (xml-text (first (filter #(= :content (:tag %)) (:content entry))))))})
- entries)))
+ (xml-text (first (filter #(= :content (:tag %)) (:content entry))))))})))
(def twitter-status-url "http://api.twitter.com/1/statuses/user_timeline.json")
@@ -55,18 +57,34 @@
:itemid (str sourceid ",id=" (:id_str tweet))
:body (:text tweet)})))
-(def fetchfns
- {:rss (fn [{:keys [url]}] (fetch-rss url))
- :twitter (fn [{:keys [user]}] (fetch-twitter user))})
+(defn send-tweet [cfg]
+ (let [creds (apply tw-oauth/make-oauth-creds ((juxt :app-key
+ :app-secret
+ :user-token
+ :user-secret)
+ (:twitter cfg)))
+ txt (subs (gen/generate-text cfg 140) 0 (min 140 (+ 40 (rand-int 140))))
+ tweet (subs txt 0 (.lastIndexOf txt " "))]
+ (println "Tweeting:" tweet)
+ (tw-rest/update-status :oauth-creds creds :params {:status tweet})))
-(defn job-exec-fn [cbc job]
+(defn fetchwrap [fetchjobfn & parmkeys]
+ (fn [job]
+ (let [items (apply fetchjobfn ((apply juxt parmkeys) job))]
+ (println "\tFetched. Inserting into Couchbase.")
+ (doseq [item items]
+ (cb/force! (:couchclient job) (:item-id item) item)))))
+
+(def jobfns
+ {:rss (fetchwrap fetch-rss :feed)
+ :twitter (fetchwrap fetch-twitter :user)
+ :send-tweet (fn [{:keys [config]}] (send-tweet config))})
+
+(defn job-exec-fn [job]
(fn []
- (println "Executing:" (pr-str job))
- (if-let [jobfn (fetchfns (:type job))]
- (let [items (jobfn job)]
- (println "\tFetched, inserting into Couchbase.")
- (doseq [item items]
- (cb/force! cbc (:item-id item) item)))
+ (println "Executing:" (pr-str (dissoc job :config :couchclient)))
+ (if-let [jobfn (jobfns (:type job))]
+ (jobfn job)
(println ".. don't know how to do that!"))))
(defn install-design-doc [fact]
@@ -83,5 +101,5 @@
cbc (cb/client cbfactory)]
(install-design-doc cbfactory)
(doseq [{:keys [period] :as job} (:jobs cfg)]
- (at-/every (* 1000 period) (job-exec-fn cbc job) atpool :initial-delay 0))))
+ (at-/every (* 1000 period) (job-exec-fn (merge job {:config cfg :couchclient cbc})) atpool :initial-delay (:after job 0)))))
View
19 src/marky/generate.clj
@@ -1,7 +1,6 @@
(ns marky.generate
(:require [cbdrawer.view :as cbv]
- [cbdrawer.client :as cb]
- [marky.collect :as collect]))
+ [cbdrawer.client :as cb]))
(defn pick [wset]
(when-not (empty? wset)
@@ -24,15 +23,13 @@
(or (last (:key selected))
(recur viewuri nil))))
-(defn generate-text [length]
- (let [cfg (collect/get-configuration)
- fact (cb/factory (:bucket cfg) (:pass cfg) (:cburl cfg))
+(defn generate-text [cfg length]
+ (let [fact (cb/factory (:bucket cfg) (:pass cfg) (:cburl cfg))
capis (cb/capi-bases fact)
viewuri (cbv/view-url capis "marky" "marky")]
- (loop [i length
- w nil]
- (let [word (next-word viewuri w)]
- (print (str word " "))
- (when (<= 0 i) (recur (- i 1) word))))))
+ (with-out-str (loop [i length
+ w nil]
+ (let [word (next-word viewuri w)]
+ (print (str word " "))
+ (when (<= 0 i) (recur (- i (count w)) word)))))))
-(defn -main [] (generate-text 50))
Please sign in to comment.
Something went wrong with that request. Please try again.