Skip to content

Instantly share code, notes, and snippets.

@gaardhus
Created March 5, 2025 12:48
Show Gist options
  • Save gaardhus/1a5e0ebd37826a521d2e2511c08bf4a3 to your computer and use it in GitHub Desktop.
Save gaardhus/1a5e0ebd37826a521d2e2511c08bf4a3 to your computer and use it in GitHub Desktop.
#!/bin/bash
# AI Chat Picker
#
# =========== #
# Description #
# =========== #
#
# This script allows the user to select an AI chat provider and enter a query,
# which is then opened in the selected provider's website.
#
# The script will:
# 1. Check if the JSON file containing the AI providers exists. If not, it will create a default one.
# 2. Fetch favicons for each provider and cache them locally.
# 3. Prompt the user to enter a query.
# 4. Display a menu of available providers with their icons.
# 5. Open the selected provider's website with the query in the default web browser.
#
#
# ============ #
# Requirements #
# ============ #
#
# - jq (for JSON parsing)
# - wget (for downloading favicons)
# - rofi (for selecting provider and entering query)
# - xdg-open (for opening the browser with the query)
#
# Author: Tobias Gårdhus
# Date: 2025-03-05
#
# ==================== #
# License: MIT License #
# ==================== #
#
# Copyright (c) 2025 Tobias Gårdhus
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# provided to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
DATA_DIR="$HOME/.local/share/ai-chat-picker"
mkdir -p "$DATA_DIR"
# Path to the JSON file containing providers
JSON_FILE="$HOME/.local/share/ai-chat-picker/providers.json"
if [ ! -f "$JSON_FILE" ]; then
echo "Error: Providers JSON file not found at $JSON_FILE. Creating default."
echo '[
{ "name": "Claude", "url": "https://claude.ai/new?q=" },
{ "name": "ChatGPT", "url": "https://chat.openai.com/?q=" },
{ "name": "Mistral", "url": "https://chat.mistral.ai/chat?q=" },
{ "name": "Open WebUI", "url": "http://localhost:8080/?q=" },
{ "name": "Perplexity", "url": "https://www.perplexity.ai/search?q=" }
]' >"$JSON_FILE"
fi
# Define favicon cache directory
ICON_DIR="$HOME/.cache/ai-chat-picker"
mkdir -p "$ICON_DIR"
# Check if the JSON file exists
if [ ! -f "$JSON_FILE" ]; then
echo "Error: Providers JSON file not found at $JSON_FILE"
exit 1
fi
# Function to fetch and cache favicons
fetch_favicon() {
local provider_name=$1
local url=$2
local host=$(echo "$url" | awk -F/ '{print $3}') # Extract domain
local icon_path="$ICON_DIR/$provider_name.png"
if [ ! -f "$icon_path" ]; then
if [ "$host" == "localhost:8080" ]; then
favicon_url="http://localhost:8080/static/favicon-96x96.png"
else
favicon_url="https://www.google.com/s2/favicons?sz=64&domain=$host"
fi
wget -qO "$icon_path" "$favicon_url"
fi
echo "$icon_path"
}
temp_file=$(mktemp)
# Process each provider
jq -r '.[] | .name + "\t" + .url' "$JSON_FILE" | while IFS=$'\t' read -r name url; do
icon_path=$(fetch_favicon "$name" "$url")
# Write to temporary file to avoid issues with null bytes
printf "%s\0icon\x1f%s\n" "$name" "$icon_path" >>"$temp_file"
done
# Prompt for query
query=$(rofi -dmenu -window-title "AI Chat picker" -p "Enter your query" -l 0 -theme-str '
window {width: 30%;}
#entry {placeholder: "Query";}
')
# Exit if no query is entered
[ -z "$query" ] && exit 1
# Prompt for provider with icons
selected_provider=$(cat "$temp_file" | rofi -dmenu -p "Select provider" -show-icons -i -no-custom)
# Clean up temp file
rm -f "$temp_file"
# Exit if no provider is selected
[ -z "$selected_provider" ] && exit 1
# Extract just the provider name (remove icon part)
provider_name=$(echo "$selected_provider" | cut -d $'\0' -f 1)
# Get the URL from the JSON file directly
url=$(jq -r ".[] | select(.name == \"$provider_name\") | .url" "$JSON_FILE")
# Open the selected provider with the query in the default browser
xdg-open "${url}$(echo "$query" | tr -d '\n' | jq -sRr @uri)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment