diff --git a/.gitignore b/.gitignore index cb856ac..4212989 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,7 @@ pom.xml.asc .hgignore .hg/ /resources/* -*~ \ No newline at end of file +*~ +*.ods + +*.csv diff --git a/CHANGELOG.md b/CHANGELOG.md index ffba40e..a5bfd74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,6 @@ # Change Log All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). -## [Unreleased] -### Changed -- Add a new arity to `make-widget-async` to provide a different widget shape. +## [0.1.0] - 2018-08-19 -## [0.1.1] - 2018-08-14 -### Changed -- Documentation on how to make the widgets. - -### Removed -- `make-widget-sync` - we're all async, all the time. - -### Fixed -- Fixed widget maker to keep working when daylight savings switches over. - -## 0.1.0 - 2018-08-14 -### Added -- Files from the new template. -- Widget maker public API - `make-widget-sync`. - -[Unreleased]: https://github.com/your-name/mastodonusers/compare/0.1.1...HEAD -[0.1.1]: https://github.com/your-name/mastodonusers/compare/0.1.0...0.1.1 +Initial release. diff --git a/README.md b/README.md index c74087a..67e69e3 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,14 @@ A Clojure app to report and log the current number of users in the fediverse. +This app depends on the API provided by [instances.social](https://instances.social/api/); +I have not investigatged the methodology by which they assemble their list of instances. In +any case it's impossible to tell how many of those accounts represent real individual human +users, and I don't currently do anything to establish how many of those accounts are active. + +Please don't use this app to DDoS `instances.social`; it really shouldn't be necessary to run +it more than once a day. + ## Configuring You should obtain a key from [instances.social](https://instances.social/api/token) and write it (just the file, nothing else) into `resources/secret.txt`. diff --git a/project.clj b/project.clj index a08a3d5..3ef2533 100644 --- a/project.clj +++ b/project.clj @@ -1,10 +1,11 @@ -(defproject mastodonusers "0.1.0-SNAPSHOT" - :description "FIXME: write description" - :url "http://example.com/FIXME" - :license {:name "Eclipse Public License" - :url "http://www.eclipse.org/legal/epl-v10.html"} +(defproject mastodonusers "0.1.0" + :description "A Clojure app to report and log the current number of users in the fediverse." + :url "https://github.com/simon-brooke/mastodonusers" + :license {:name "GNU General Public License,version 2.0" + :url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"} :dependencies [[org.clojure/clojure "1.8.0"] [org.clojure/data.json "0.2.6"] + [org.clojure/tools.cli "0.3.7"] [clj-http "3.9.1"] [clj-time "0.14.4"]] :aot [mastodonusers.core] diff --git a/src/mastodonusers/core.clj b/src/mastodonusers/core.clj index 2d58255..9ecbe01 100644 --- a/src/mastodonusers/core.clj +++ b/src/mastodonusers/core.clj @@ -1,25 +1,65 @@ (ns mastodonusers.core (:require [clojure.data.json :as json] [clojure.pprint :refer :all] + [clojure.string :as s] + [clojure.tools.cli :refer [parse-opts]] [clojure.walk :refer [keywordize-keys]] [clj-http.client :as h] [clj-time.core :as t] [clj-time.format :as f]) (:gen-class)) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; +;;;; mastodonusers.core +;;;; +;;;; This program is free software; you can redistribute it and/or +;;;; modify it under the terms of the GNU General Public License +;;;; as published by the Free Software Foundation; either version 2 +;;;; of the License, or (at your option) any later version. +;;;; +;;;; This program is distributed in the hope that it will be useful, +;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;;; GNU General Public License for more details. +;;;; +;;;; You should have received a copy of the GNU General Public License +;;;; along with this program; if not, write to the Free Software +;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +;;;; USA. +;;;; +;;;; Copyright (C) 2018 Simon Brooke +;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; (def application-id "431276798") -;; (def application-name "mastodonusers") +(def cli-options + [["-h" "--help" "Show this message" + :default false] + ["-o" "--csv" "output data as comma-separated values"] + ["-s" "--bearer-secret [SECRET]" "The secret which identifies us to instances.social"] + ["-v" "--verbosity [LEVEL]" nil "Verbosity level - integer value required" + :parse-fn #(Integer/parseInt %) + :default 0] + ]) + + +(defn usage + "Show a usage message. `options` should be options as + parsed by [clojure.tools.cli](https://github.com/clojure/tools.cli)" + [options] + (println (:summary options))) (defn fetch-data - "Fetch current data from instances.social with our key" - [] + "Fetch current data from instances.social with this `secret` key" + [secret] (h/get "https://instances.social/api/1.0/instances/list" {:headers {:authorization (str "Bearer " - (slurp "resources/secret.txt"))} + (or + secret + (slurp "resources/secret.txt")))} :query-params {:count 0} :accept :json})) @@ -61,14 +101,68 @@ c))))) -(defn -main [& args] +(defn ->csv + "Return the contents of this EDN `file`, assumed to contain a map with + date/time keys and count values, in CSV format." + [file] + (let [data (read-string (slurp file))] + (s/join + "\n" + (map + #(str % ", " (data %)) + (sort + #(compare + (f/parse + ;; (f/formatters :basic-date-time) + %1) + (f/parse + ;; (f/formatters :basic-date-time) + %2)) + (keys data)))))) + + +(defn process + "Process these parsed `options`." + [options] + (let [c (count-users + (fetch-data + (-> options :options :bearer-secret))) + args (:arguments options)] + (if-not + (empty? args) + (update-file (first args) c)) + (if-not + (zero? (-> options :options :verbosity)) + (println "Total #fediverse user accounts: " c)) + (if + (and + (not (empty? args)) + (-> options :options :csv)) + (println (->csv (first args)))) + c)) + + +(defn -main "Print a count of the current number of user accounts in the fediverse. If an argument is present, it is presumed to be the pathname of an EDN formatted file containing a map mapping times to counts, which will be updated with the current count." - (let [c (count-users (fetch-data))] - (if-not (empty? args) (update-file (first args) c)) - (println "Total #fediverse user accounts: " c) - c)) + [& args] + (let [options (parse-opts args cli-options)] + (cond + (empty? args) + (usage options) + (seq (:errors options)) + (do + (doall + (map + println + (:errors options))) + (usage options)) + (-> options :options :help) + (usage options) + true + (process options)))) +