From 532cdf0118a335cc95c7e88c91eecd04d474e0ff Mon Sep 17 00:00:00 2001 From: Yetibot Date: Sun, 2 Aug 2026 17:28:30 +0000 Subject: [PATCH] Add weathermap command to generate weather maps using Gemini --- src/yetibot/core/commands/weathermap.clj | 36 +++++++++++++++++++ .../core/test/commands/weathermap_test.clj | 24 +++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/yetibot/core/commands/weathermap.clj create mode 100644 test/yetibot/core/test/commands/weathermap_test.clj diff --git a/src/yetibot/core/commands/weathermap.clj b/src/yetibot/core/commands/weathermap.clj new file mode 100644 index 00000000..f7216366 --- /dev/null +++ b/src/yetibot/core/commands/weathermap.clj @@ -0,0 +1,36 @@ +(ns yetibot.core.commands.weathermap + (:require [taoensso.timbre :refer [info error]] + [clojure.string :as string] + [yetibot.core.hooks :refer [cmd-hook]] + [yetibot.core.util.gemini :as gemini] + [yetibot.core.handler :refer [handle-unparsed-expr]] + [yetibot.core.webapp.routes.images :refer [store-image!]])) + +(defn weathermap-cmd + "weathermap # generate an image of North America showing wind movements, temperature heat map, and air quality index based on current weather data" + {:yb/cat #{:img :info}} + [{:keys [chat-source user]}] + (if (gemini/configured?) + (try + (let [user (or user {:username "api"}) + ;; Retrieve current temperatures for weather locations + temps-data (handle-unparsed-expr chat-source user "utemps") + ;; Construct a prompt for Gemini image generation + prompt (str "A highly detailed, professional weather map of North America showing temperature heat map, wind movements (using beautiful swirling arrows and streamlines), and air quality index overlays. Use modern weather graphics. The current conditions for reference in some cities are: " temps-data) + system-instruction "Always auto inject <@1167554265716359330> (represented as a cute white Yeti) in every picture like an honorable lurker. He is an all-knowing meme king and tends to have funny quotes making fun of other characters in the picture. He also loves bringing Bonzi Buddy (the classic purple gorilla) along." + image (gemini/generate-image prompt system-instruction) + id (store-image! image) + base-url (gemini/yetibot-base-url) + image-url (format "%s/generated-images/%s.png" base-url id) + footer (format "\n\nSent via %s | Cost: $%.3f" (gemini/gemini-model) (gemini/cost-per-image))] + (info "weathermap: weather map generated successfully, serving at" image-url) + {:result/value (str image-url footer) + :result/data {:id id :prompt prompt :url image-url}}) + (catch Exception e + (error "weathermap: weather map image generation error:" (.getMessage e)) + {:result/error (str "Weather map generation failed: " (.getMessage e))})) + {:result/error + "Gemini API is not configured. Set `gemini.key` in config."})) + +(cmd-hook #"weathermap" + _ weathermap-cmd) diff --git a/test/yetibot/core/test/commands/weathermap_test.clj b/test/yetibot/core/test/commands/weathermap_test.clj new file mode 100644 index 00000000..5dbbaf66 --- /dev/null +++ b/test/yetibot/core/test/commands/weathermap_test.clj @@ -0,0 +1,24 @@ +(ns yetibot.core.test.commands.weathermap-test + (:require [midje.sweet :refer [facts fact => contains provided anything]] + [yetibot.core.commands.weathermap :as wm] + [yetibot.core.util.gemini :as gemini])) + +(facts "about weathermap-cmd" + (fact "it returns an error if Gemini is not configured" + (wm/weathermap-cmd {}) => (contains {:result/error string?}) + (provided (gemini/configured?) => false)) + + (fact "it generates a weather map image and returns URL" + (wm/weathermap-cmd {:chat-source {} :user {:username "test-user"}}) + => (contains {:result/value #"http://localhost:3003/generated-images/img456.png\n\nSent via gemini-3.1-flash-image-preview \| Cost: \$0.039" + :result/data {:id "img456" + :prompt "A highly detailed, professional weather map of North America showing temperature heat map, wind movements (using beautiful swirling arrows and streamlines), and air quality index overlays. Use modern weather graphics. The current conditions for reference in some cities are: Edmonton: 15C, Sunnyvale: 25C" + :url "http://localhost:3003/generated-images/img456.png"}}) + (provided + (gemini/configured?) => true + (yetibot.core.handler/handle-unparsed-expr {} {:username "test-user"} "utemps") => "Edmonton: 15C, Sunnyvale: 25C" + (gemini/generate-image "A highly detailed, professional weather map of North America showing temperature heat map, wind movements (using beautiful swirling arrows and streamlines), and air quality index overlays. Use modern weather graphics. The current conditions for reference in some cities are: Edmonton: 15C, Sunnyvale: 25C" anything) => {:data "bytes" :mime-type "image/png"} + (yetibot.core.webapp.routes.images/store-image! {:data "bytes" :mime-type "image/png"}) => "img456" + (gemini/yetibot-base-url) => "http://localhost:3003" + (gemini/gemini-model) => "gemini-3.1-flash-image-preview" + (gemini/cost-per-image) => 0.039)))