Last active
April 16, 2024 10:14
-
-
Save choffee/a56effb8aab913c4680658187f0fead7 to your computer and use it in GitHub Desktop.
Cli tool for selecting DuckDuckGo bang searches unsing Babashka and gum.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bb | |
;; Script to search ddg. | |
;; Takes a search term then asks you to select a bang. | |
;; Copyright John Cooper | |
;; 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 3 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, see <https://www.gnu.org/licenses/>. | |
;; Ideas for how it would work. | |
;; ddg _dpkg foobar => !dpkg foobar | |
;; ddg -b dpkg foobar => !dpkg foobar | |
;; ddg foobar => prompt for banging search param. | |
;; (let [cacheurl "https://duckduckgo.com/bang.v260.js"]) | |
;; You need to install gum from https://charm.sh | |
(babashka.deps/add-deps | |
'{:deps {io.github.lispyclouds/bblgum {:git/sha "7ebae0e2231899fe2a6ad44bc9ef5fca64099fcd"}}}) | |
(ns bin.ddg | |
(:require [babashka.process :as p] | |
[clojure.string :as str] | |
[babashka.http-client :as http] | |
[cheshire.core :as json] | |
[babashka.fs :as fs] | |
[bblgum.core :as b])) | |
(def cache-file (str (fs/path (fs/xdg-cache-home) "ddg_bangs.json"))) | |
(defn cache_valid? [filename seconds] | |
"Is a file older than x seconds?" | |
(and (fs/exists? cache-file) | |
(> (+ (* seconds 1000) (fs/file-time->millis (fs/last-modified-time filename))) | |
(System/currentTimeMillis)))) | |
(defn get_bangs_json [] | |
"Fetch the list of bangs from DDG | |
Later cache it..." | |
(let [cacheurl "https://duckduckgo.com/bang.js"] | |
(json/parse-string | |
(cond | |
(cache_valid? cache-file (* 60 60 24)) | |
(slurp cache-file) | |
:else | |
(let [cache-data (:body (http/get cacheurl {:headers {"Accept" "application/json" "user-agent" "curl/7.87.0"} :throw false}))] | |
(spit cache-file cache-data) | |
cache-data))))) | |
(defn open_ddg [searchterm] | |
"Given a search term open DuckDuckGo in default browser" | |
(p/shell "xdg-open" (str "https://duckduckgo.com/?q=" searchterm))) | |
;; => {"c" "Tech", "d" "www.01net.com", "r" 6, "s" "01net", "sc" "Downloads (apps)", "t" "01net", "u" "http://www.01net.com/recherche/recherche.php?searchstring={{{s}}}&chaine=home"} | |
(defn bang->selector [bang] | |
"Takes in a bang json and returns a string for selecting" | |
(str/join ": " (list (get bang "t") (get bang "s") (get bang "sc")))) | |
(defn selector->bang [selector_string] | |
"Give the bang string from the selector" | |
(first (str/split selector_string #":"))) | |
(defn bangs_json->gumlist [bangs_json] | |
(map bang->selector bangs_json)) | |
(defn ask_for_bang [bangs_json] | |
"Ask user to select the bang for the search" | |
(->> | |
(b/gum {:cmd :filter | |
:in (str/join "\n" (bangs_json->gumlist bangs_json))}) | |
:result | |
first | |
selector->bang)) | |
(defn search_term [bang args] | |
(->> | |
(str/join " " args) | |
(str "!" bang " "))) | |
(let [bangs_json (get_bangs_json)] | |
(open_ddg (search_term (ask_for_bang bangs_json) *command-line-args*))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've updated the url of the bangs to a more generic one so it works again now and should not need updating.