diff --git a/src/main/lemondronor/advisorycircular.cljs b/src/main/lemondronor/advisorycircular.cljs index a4ccdbf..0c67a7c 100644 --- a/src/main/lemondronor/advisorycircular.cljs +++ b/src/main/lemondronor/advisorycircular.cljs @@ -23,6 +23,10 @@ (def log-prefix (atom "")) +(defn parse-json [s] + (.parse js/JSON s)) + + (defn get-basestation-sqb-record [icao db-path] (log-info "%s: Looking up in %s" icao db-path) (p/let [record @@ -59,7 +63,7 @@ {:aircraft (map parse-adsbexchange-ac-element (get - (js->clj (.parse js/JSON json-str)) + (js->clj (parse-json json-str)) "ac"))}) @@ -167,7 +171,7 @@ (defn read-history-db [path] (p/let [json-str (util/read-file path {:encoding "utf-8"}) - db (js->clj (.parse js/JSON json-str) :keywordize-keys true) + db (js->clj (parse-json json-str) :keywordize-keys true) db (into {} (map (fn [[k v]] [(name k) v]) db))] (log-verbose "Loaded %s aircraft from database %s" (count db) path) db)) @@ -203,6 +207,34 @@ image-path))) +(defn airport-data-aircraft-photo [icao reg] + (log-info "%s: Geting aircraft-data photo" icao) + (let [query (cond-> {:m icao :n 1} + reg + (assoc :r reg))] + (p/let [r (util/http-get "https://www.airport-data.com/api/ac_thumb.json" + {:query query})] + (let [r (js->clj (parse-json r) :keywordize-keys true)] + (if (and (:data r) (> (count (:data r)) 0)) + (p/let [url (get-in r [:data 0 :image]) + image (util/http-get url {:encoding nil})] + image) + (do + (log-info "%s: No aircraft-data photo available" icao) + nil)))))) + + +(defn aircraft-photo [icao registration] + (p/let [photo (p/race [(p/let [_ (util/timeout 7000)] + :timeout) + (airport-data-aircraft-photo icao registration)])] + (if (= photo :timeout) + (do + (log-warn "%s: airport-data API timed out" icao) + nil) + photo))) + + (defn circling? [ac config] (and (> (geo/flight-curviness (filter #(not (:gnd? %)) (:history ac))) (:curviness-threshold-degrees config)) @@ -546,6 +578,7 @@ (log-error "%s: Reverse geocode failed: %s" icao coarse)) ;; Note that if we're over the ocean we get null :( (p/then (p/all [(map-screenshot (:icao ac) lat lon now (:screenshot config)) + (aircraft-photo (:icao ac) (:registration ac)) (p/let [nearby (landmark config lat lon) ;;_ (log-info "WOOO %s" nearby) sqb (if-let [sqb-path (:basestation-sqb config)] @@ -553,19 +586,19 @@ (let [description (generate-description ac sqb coarse nearby)] (log-info "%s Description: %s" (:icao ac) description) description))]) - (fn [[image-path description]] + (fn [[screenshot-path ac-photo description]] (if (or (nil? coarse) ;; TODO: Filter using the layer hierarchy; we want ;; anything smaller than "region" (state). ;;(= (get-in coarse [:properties :name]) "California") ) (log-info "%s: Filtering out because we have insuffucient reverse geo info" (:icao ac)) - (if (and image-path description) - (p/let [image (util/read-file image-path)] + (if (and screenshot-path description) + (p/let [screenshot-image (util/read-file screenshot-path)] (if (get-in config [:twitter :enabled?]) (twitter/tweet (twitter/twit (:twitter config)) description - [image] + (remove nil? [screenshot-image ac-photo]) lat lon) (log-warn "Skipping tweeting")) @@ -577,7 +610,7 @@ js/JSON (clj->js (track->geojson older-positions recent-positions icao centroid))) {}))) - (log-warn "Skipping tweet %s %s" image-path description))))))))))) + (log-warn "Skipping tweet %s %s" screenshot-path description))))))))))) (defn process-potential-circles [acs config now] @@ -691,11 +724,8 @@ geojson (airport-geojson config)] (println (.stringify js/JSON (clj->js geojson) nil " "))) (.-test commander) - (do - (print (.from js/Buffer #js [1 2 3 4])) - (print (.from js/Buffer (.from js/Buffer #js [1 2 3 4]))) - (print (.toString (.from js/Buffer (.from js/Buffer #js [1 2 3 4])) "base64")) - ) + (p/let [photo (airport-data-aircraft-photo (.-icao commander) (.-reg commander))] + (fs/writeFileSync "photo.jpg" photo)) :else (let [start-time (current-time)] ;; If --config-path is specified, definitely try to read that diff --git a/src/main/lemondronor/advisorycircular/adsbx.cljs b/src/main/lemondronor/advisorycircular/adsbx.cljs index 99dae1a..2f9f50e 100644 --- a/src/main/lemondronor/advisorycircular/adsbx.cljs +++ b/src/main/lemondronor/advisorycircular/adsbx.cljs @@ -8,6 +8,7 @@ [goog.string :as gstring] [kitchen-async.promise :as p] [lemondronor.advisorycircular.logging :as logging] + [lemondronor.advisorycircular.util :as util] goog.string.format)) (declare logger log-debug log-verbose log-info log-warn log-error) @@ -28,14 +29,6 @@ ;; (drop 1 pieces-remaining)))))) -(defn timeout - ([ms] - (timeout ms nil)) - ([ms v] - (p/promise [resolve] - (js/setTimeout #(resolve v) ms)))) - - (defn current-time-secs [] (/ (.getTime (js/Date.)) 1000)) @@ -88,15 +81,15 @@ (.goto page url (clj->js {:referer "https://adsbexchange.com/"}))])) - (timeout 100) + (util/timeout 100) (when-let [layer (:layer options)] (.evaluate page (str "ol.control.LayerSwitcher.forEachRecursive(layers_group, l => { if (l.get('name') == '" layer "') { console.log(l.get('name')); ol.control.LayerSwitcher.setVisible_(OLMap, l, true); } });"))) - (timeout 2900) + (util/timeout 2900) (delete-node page "#adsense") (p/all [(.type (.-keyboard page) "l") - (timeout 2000)]) + (util/timeout 2000)]) (let [path (get options :output-path (str "screenshot-" (.toFixed (current-time-secs) 0) "-" diff --git a/src/main/lemondronor/advisorycircular/twitter.cljs b/src/main/lemondronor/advisorycircular/twitter.cljs index 152a21f..813fac9 100644 --- a/src/main/lemondronor/advisorycircular/twitter.cljs +++ b/src/main/lemondronor/advisorycircular/twitter.cljs @@ -29,7 +29,7 @@ (p/let [b64content (.toString (.from js/Buffer image) "base64") result (.post twit "media/upload" (clj->js {:media_data b64content})) media-id (get-in (js->clj result :keywordize-keys true) [:data :media_id_string])] - (log-info "%s got media ID %s" media-id) + (log-info "Got media ID %s" media-id) media-id)) diff --git a/src/main/lemondronor/advisorycircular/util.cljs b/src/main/lemondronor/advisorycircular/util.cljs index ac2c598..54a0ae4 100644 --- a/src/main/lemondronor/advisorycircular/util.cljs +++ b/src/main/lemondronor/advisorycircular/util.cljs @@ -105,3 +105,11 @@ (defn feet-to-meters [f] (* f 0.3048)) + + +(defn timeout + ([ms] + (timeout ms nil)) + ([ms v] + (p/promise [resolve] + (js/setTimeout #(resolve v) ms))))