|
|
|
@ -2,19 +2,42 @@
|
|
|
|
|
(:require [clj-http.client :as client])
|
|
|
|
|
(:require [clojure.data.json :as json]))
|
|
|
|
|
|
|
|
|
|
(def POST-LIST "/post/list")
|
|
|
|
|
(def COMMENTS "/comment/list")
|
|
|
|
|
|
|
|
|
|
(defn make-api-url [inst endpoint]
|
|
|
|
|
(str "https://" inst "/api/v3" endpoint))
|
|
|
|
|
|
|
|
|
|
(defn api-call [api-url query-params]
|
|
|
|
|
(def DEFAULT-INSTANCE
|
|
|
|
|
"The default instance to access."
|
|
|
|
|
"lemmy.ml")
|
|
|
|
|
(def POST-PAGESIZE
|
|
|
|
|
"Number of posts to show per 'page'. Set by the API."
|
|
|
|
|
5)
|
|
|
|
|
(def COMMENT-PAGESIZE
|
|
|
|
|
"Number of comments to show per 'page'. Kept low for smaller screens."
|
|
|
|
|
1)
|
|
|
|
|
(def COMMENT-LIMIT
|
|
|
|
|
"Maximum number of comments to retrieve for a post."
|
|
|
|
|
50)
|
|
|
|
|
|
|
|
|
|
(def POST-LIST
|
|
|
|
|
"API endpoint for post list."
|
|
|
|
|
"/post/list")
|
|
|
|
|
(def COMMENTS
|
|
|
|
|
"API endpoint for comment list (of a given post)."
|
|
|
|
|
"/comment/list")
|
|
|
|
|
|
|
|
|
|
(defn make-api-url
|
|
|
|
|
"Builds URL for API request given the instance and endpoint."
|
|
|
|
|
[inst endpoint]
|
|
|
|
|
(str "https://" inst "/api/v3" endpoint))
|
|
|
|
|
|
|
|
|
|
(defn api-call
|
|
|
|
|
"Completes an API request, returning the processed JSON."
|
|
|
|
|
[api-url query-params]
|
|
|
|
|
(-> api-url
|
|
|
|
|
(client/get {:accept :json :query-params query-params})
|
|
|
|
|
(get :body)
|
|
|
|
|
(json/read-str)))
|
|
|
|
|
|
|
|
|
|
(defn post-list [instance community page]
|
|
|
|
|
(defn post-list
|
|
|
|
|
"Fetches a post list from the given instance and endpoint."
|
|
|
|
|
[instance community page]
|
|
|
|
|
(let [query-params (cond-> {:sort "Hot" :page (str page)}
|
|
|
|
|
(not (empty? community))
|
|
|
|
|
(assoc :community_name community))]
|
|
|
|
@ -22,12 +45,17 @@
|
|
|
|
|
(api-call query-params)
|
|
|
|
|
(get "posts"))))
|
|
|
|
|
|
|
|
|
|
(defn comments-list [instance post]
|
|
|
|
|
(defn comments-list
|
|
|
|
|
"Fetches the comment list for a given post."
|
|
|
|
|
[instance post]
|
|
|
|
|
(-> (make-api-url instance COMMENTS)
|
|
|
|
|
(api-call {:limit "50" :post_id (str (get-in post ["post" "id"]))})
|
|
|
|
|
(api-call {:limit (str COMMENT-LIMIT)
|
|
|
|
|
:post_id (str (get-in post ["post" "id"]))})
|
|
|
|
|
(get "comments")))
|
|
|
|
|
|
|
|
|
|
(defn show-post-item [index post]
|
|
|
|
|
(defn show-post-item
|
|
|
|
|
"Renders a listing of the given post. Index is for user selection."
|
|
|
|
|
[index post]
|
|
|
|
|
(let [items [["creator" "name"]
|
|
|
|
|
["community" "name"]
|
|
|
|
|
["post" "name"]
|
|
|
|
@ -36,26 +64,35 @@
|
|
|
|
|
data (cons (inc index) (mapv (partial get-in post) items))]
|
|
|
|
|
(apply (partial printf "%d. %s on %s\n %s\n at %s (%d comments)\n\n") data)))
|
|
|
|
|
|
|
|
|
|
(defn show-comment-item [commnt]
|
|
|
|
|
(defn show-comment-item
|
|
|
|
|
"Renders the given comment (from a post)."
|
|
|
|
|
[commnt]
|
|
|
|
|
(println (get-in commnt ["creator" "name"]) "says:")
|
|
|
|
|
(println (get-in commnt ["comment" "content"]))
|
|
|
|
|
(println)
|
|
|
|
|
)
|
|
|
|
|
(println))
|
|
|
|
|
|
|
|
|
|
(defn show-posts [posts]
|
|
|
|
|
(doseq [index (range 0 5)]
|
|
|
|
|
(defn show-posts
|
|
|
|
|
"Displays a page's worth of post listings."
|
|
|
|
|
[posts]
|
|
|
|
|
(doseq [index (range 0 POST-PAGESIZE)]
|
|
|
|
|
(show-post-item index (nth posts index))))
|
|
|
|
|
|
|
|
|
|
(defn show-comments [comments]
|
|
|
|
|
(doseq [commnt (take 1 comments)]
|
|
|
|
|
(defn show-comments
|
|
|
|
|
"Displays a page's worth of comments."
|
|
|
|
|
[comments]
|
|
|
|
|
(doseq [commnt (take COMMENT-PAGESIZE comments)]
|
|
|
|
|
(show-comment-item commnt)))
|
|
|
|
|
|
|
|
|
|
(defn show-posts-prompt []
|
|
|
|
|
(print "#NPQ> ")
|
|
|
|
|
(defn show-posts-prompt
|
|
|
|
|
"Collects user input at post listing menu."
|
|
|
|
|
[]
|
|
|
|
|
(print "#NPCIQ> ")
|
|
|
|
|
(flush)
|
|
|
|
|
(first (read-line)))
|
|
|
|
|
|
|
|
|
|
(defn show-comments-prompt []
|
|
|
|
|
(defn show-comments-prompt
|
|
|
|
|
"Collects user input at comment listing menu."
|
|
|
|
|
[]
|
|
|
|
|
(print "BNP> ")
|
|
|
|
|
(flush)
|
|
|
|
|
(first (read-line)))
|
|
|
|
@ -66,37 +103,90 @@
|
|
|
|
|
(read-line))
|
|
|
|
|
|
|
|
|
|
(defn show-instance-prompt []
|
|
|
|
|
(print "Enter instance name [lemmy.ml]: ")
|
|
|
|
|
(printf "Enter instance name [%s]: " DEFAULT-INSTANCE)
|
|
|
|
|
(flush)
|
|
|
|
|
(let [inst (read-line)] (if (empty? inst) "lemmy.ml" inst)))
|
|
|
|
|
(let [inst (read-line)] (if (empty? inst) DEFAULT-INSTANCE inst)))
|
|
|
|
|
|
|
|
|
|
(defn view-post [instance post]
|
|
|
|
|
(defn view-post
|
|
|
|
|
"Main loop for viewing a post and its comments."
|
|
|
|
|
[instance post]
|
|
|
|
|
(loop [offset 0 comments (comments-list instance post)]
|
|
|
|
|
(println)
|
|
|
|
|
(show-comments (if (pos? offset) (drop (* 1 offset) comments) comments))
|
|
|
|
|
(show-comments (drop (* COMMENT-PAGESIZE offset) comments))
|
|
|
|
|
(case (show-comments-prompt)
|
|
|
|
|
\B (println)
|
|
|
|
|
\N (recur (inc offset) comments)
|
|
|
|
|
\P (recur (dec offset) comments)
|
|
|
|
|
(do (println "Unknown command.") (recur offset comments)))))
|
|
|
|
|
|
|
|
|
|
(defn view-page [instance init-community]
|
|
|
|
|
(loop [top true community init-community page 1 posts (post-list instance community page)]
|
|
|
|
|
(defn view-nth-post
|
|
|
|
|
"Views the index-th post from the current post list."
|
|
|
|
|
[state posts index]
|
|
|
|
|
(view-post
|
|
|
|
|
(:instance state)
|
|
|
|
|
(nth posts (cond-> (+ 5 index) (:top state) (- 5))))
|
|
|
|
|
state)
|
|
|
|
|
|
|
|
|
|
(defn get-post-list
|
|
|
|
|
"Fetches a new list of posts given the current (view-page) state."
|
|
|
|
|
[state]
|
|
|
|
|
(post-list (:instance state) (:community state) (:page state)))
|
|
|
|
|
|
|
|
|
|
(defn next-page
|
|
|
|
|
"Updates state for viewing the next page of posts."
|
|
|
|
|
[state]
|
|
|
|
|
(if (:top state)
|
|
|
|
|
(assoc state :top false)
|
|
|
|
|
(-> state (assoc :top true) (update :page inc))))
|
|
|
|
|
|
|
|
|
|
(defn prev-page
|
|
|
|
|
"Updates state for viewing the previous page of posts."
|
|
|
|
|
[state]
|
|
|
|
|
(if-not (:top state)
|
|
|
|
|
(assoc state :top true)
|
|
|
|
|
(-> state (assoc :top false) (update :page dec))))
|
|
|
|
|
|
|
|
|
|
(defn change-community
|
|
|
|
|
"Updates state for viewing a different community."
|
|
|
|
|
[state]
|
|
|
|
|
(-> state
|
|
|
|
|
(assoc :top true)
|
|
|
|
|
(assoc :page 1)
|
|
|
|
|
(assoc :community (show-community-prompt))))
|
|
|
|
|
|
|
|
|
|
(defn change-instance
|
|
|
|
|
"Updates state for viewing a different instance."
|
|
|
|
|
[state]
|
|
|
|
|
(-> state
|
|
|
|
|
(assoc :instance (show-instance-prompt))
|
|
|
|
|
(change-community)))
|
|
|
|
|
|
|
|
|
|
(defn view-page
|
|
|
|
|
"Main loop for viewing posts listings."
|
|
|
|
|
[init-instance init-community]
|
|
|
|
|
(loop [state {:top true
|
|
|
|
|
:instance init-instance
|
|
|
|
|
:community init-community
|
|
|
|
|
:page 1}
|
|
|
|
|
posts (get-post-list state)]
|
|
|
|
|
(println)
|
|
|
|
|
(show-posts (if top posts (drop 5 posts)))
|
|
|
|
|
(show-posts (if (:top state) posts (drop POST-PAGESIZE posts)))
|
|
|
|
|
(case (show-posts-prompt)
|
|
|
|
|
\N (if top (recur false community page posts)
|
|
|
|
|
(recur true community (inc page) (post-list instance community (inc page))))
|
|
|
|
|
\P (if top (recur false community (dec page) (post-list instance community (dec page)))
|
|
|
|
|
(recur true community page posts))
|
|
|
|
|
\N (let [new-state (next-page state)]
|
|
|
|
|
(recur new-state (if (:top new-state) (get-post-list new-state) posts)))
|
|
|
|
|
\P (let [new-state (prev-page state)]
|
|
|
|
|
(recur new-state (if (:top new-state) posts (get-post-list new-state))))
|
|
|
|
|
\Q (println)
|
|
|
|
|
\1 (do (view-post instance (nth posts (cond-> 5 top (- 5)))) (recur top community page posts))
|
|
|
|
|
\2 (do (view-post instance (nth posts (cond-> 6 top (- 5)))) (recur top community page posts))
|
|
|
|
|
\3 (do (view-post instance (nth posts (cond-> 7 top (- 5)))) (recur top community page posts))
|
|
|
|
|
\4 (do (view-post instance (nth posts (cond-> 8 top (- 5)))) (recur top community page posts))
|
|
|
|
|
\5 (do (view-post instance (nth posts (cond-> 9 top (- 5)))) (recur top community page posts))
|
|
|
|
|
\C (let [comm (show-community-prompt)] (recur true comm 1 (post-list instance comm page)))
|
|
|
|
|
(do (println "Unknown command.") (recur top community page posts)))))
|
|
|
|
|
\1 (recur (view-nth-post state posts 0) posts)
|
|
|
|
|
\2 (recur (view-nth-post state posts 1) posts)
|
|
|
|
|
\3 (recur (view-nth-post state posts 2) posts)
|
|
|
|
|
\4 (recur (view-nth-post state posts 3) posts)
|
|
|
|
|
\5 (recur (view-nth-post state posts 4) posts)
|
|
|
|
|
\C (let [new-state (change-community state)]
|
|
|
|
|
(recur new-state (get-post-list new-state)))
|
|
|
|
|
\I (let [new-state (change-instance state)]
|
|
|
|
|
(recur new-state (get-post-list new-state)))
|
|
|
|
|
(do (println "Unknown command.") (recur state posts)))))
|
|
|
|
|
|
|
|
|
|
(defn -main [& args]
|
|
|
|
|
(println "Welcome to lemmold, your old-school Lemmy browser!")
|
|
|
|
|