Merge branch 'master' into develop

This commit is contained in:
Simon Brooke 2018-08-24 23:29:01 +01:00
commit 58258ec40d
5 changed files with 124 additions and 36 deletions

5
.gitignore vendored
View file

@ -10,4 +10,7 @@ pom.xml.asc
.hgignore
.hg/
/resources/*
*~
*~
*.ods
*.csv

View file

@ -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.

View file

@ -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`.

View file

@ -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]

View file

@ -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))))