changes :3
This commit is contained in:
parent
c50bfc3eea
commit
0ad695abcf
27 changed files with 1022 additions and 656 deletions
323
modules/home/scripts/opsearch.sh
Executable file
323
modules/home/scripts/opsearch.sh
Executable file
|
|
@ -0,0 +1,323 @@
|
|||
#!/usr/bin/env bash
|
||||
# opsearch.sh - A tool to search through 1Password items
|
||||
#
|
||||
# Usage:
|
||||
# opsearch <search_term> [options]
|
||||
#
|
||||
# Options:
|
||||
# -c, --category Filter by category (login, password, document, etc.)
|
||||
# -t, --tag Filter by tag
|
||||
# -v, --vault Specify vault to search in
|
||||
# -f, --field Search only in specific fields
|
||||
# -j, --json Output results in JSON format
|
||||
# -d, --detail Show detailed output for each item
|
||||
# -n, --nushell Use Nushell for output formatting (if available)
|
||||
# -p, --password Retrieve and copy password after selection
|
||||
# -h, --help Show this help message
|
||||
|
||||
set -e
|
||||
|
||||
# Default options
|
||||
FORMAT="json"
|
||||
SHOW_DETAIL=false
|
||||
CATEGORY=""
|
||||
TAG=""
|
||||
VAULT=""
|
||||
FIELD=""
|
||||
SEARCH_TERM=""
|
||||
USE_NUSHELL=false
|
||||
GET_PASSWORD=false
|
||||
|
||||
# Check if 1Password CLI is available
|
||||
if ! command -v op &>/dev/null; then
|
||||
echo "Error: 1Password CLI (op) not found."
|
||||
echo "Please install it from https://1password.com/downloads/command-line/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if 1Password CLI is signed in
|
||||
if ! op account get --format=json &>/dev/null; then
|
||||
echo "You need to sign in to 1Password CLI first."
|
||||
echo "Run: eval \$(op signin)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to display help
|
||||
show_help() {
|
||||
cat << EOF
|
||||
opsearch - Search 1Password items with grep-like functionality
|
||||
|
||||
Usage:
|
||||
opsearch <search_term> [options]
|
||||
|
||||
Options:
|
||||
-c, --category <category> Filter by category (login, password, document, etc.)
|
||||
-t, --tag <tag> Filter by tag
|
||||
-v, --vault <vault> Specify vault to search in
|
||||
-f, --field <field> Search only in specific fields
|
||||
-j, --json Output results in JSON format
|
||||
-d, --detail Show detailed output for each item
|
||||
-n, --nushell Use Nushell for output formatting (if available)
|
||||
-p, --password Retrieve and copy password after selection
|
||||
-h, --help Show this help message
|
||||
|
||||
Examples:
|
||||
opsearch github # Search for "github" in all items
|
||||
opsearch amazon -c login # Search for "amazon" in login items
|
||||
opsearch bank -v Personal # Search for "bank" in the Personal vault
|
||||
opsearch -t finance # Show all items with "finance" tag
|
||||
opsearch email -f username # Search for "email" in username fields
|
||||
opsearch ssh -d # Show detailed info for SSH items
|
||||
opsearch github -p # Get GitHub password after selecting item
|
||||
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
show_help
|
||||
;;
|
||||
-j|--json)
|
||||
FORMAT="json"
|
||||
shift
|
||||
;;
|
||||
-d|--detail)
|
||||
SHOW_DETAIL=true
|
||||
shift
|
||||
;;
|
||||
-n|--nushell)
|
||||
USE_NUSHELL=true
|
||||
shift
|
||||
;;
|
||||
-p|--password)
|
||||
GET_PASSWORD=true
|
||||
shift
|
||||
;;
|
||||
-c|--category)
|
||||
CATEGORY="$2"
|
||||
shift 2
|
||||
;;
|
||||
-t|--tag)
|
||||
TAG="$2"
|
||||
shift 2
|
||||
;;
|
||||
-v|--vault)
|
||||
VAULT="$2"
|
||||
shift 2
|
||||
;;
|
||||
-f|--field)
|
||||
FIELD="$2"
|
||||
shift 2
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option: $1"
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
if [[ -z "$SEARCH_TERM" ]]; then
|
||||
SEARCH_TERM="$1"
|
||||
else
|
||||
echo "Error: Multiple search terms provided. Use quotes for terms with spaces."
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check for required tools
|
||||
check_dependencies() {
|
||||
if ! command -v jq &> /dev/null; then
|
||||
echo "Error: jq is required for this script to function properly."
|
||||
echo "Please install it using your package manager."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$USE_NUSHELL" == "true" ]] && ! command -v nu &> /dev/null; then
|
||||
echo "Warning: Nushell not found, falling back to jq for formatting."
|
||||
USE_NUSHELL=false
|
||||
fi
|
||||
|
||||
if [[ "$GET_PASSWORD" == "true" ]]; then
|
||||
if ! command -v xclip &> /dev/null && ! command -v pbcopy &> /dev/null && ! command -v wl-copy &> /dev/null; then
|
||||
echo "Warning: No clipboard utility found (xclip, pbcopy, or wl-copy required)."
|
||||
echo "Password will be displayed but not copied."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Build the 1Password CLI command
|
||||
OP_CMD="op item list --format=json"
|
||||
|
||||
# Add filters to the command
|
||||
if [[ -n "$CATEGORY" ]]; then
|
||||
OP_CMD="$OP_CMD --categories=$CATEGORY"
|
||||
fi
|
||||
|
||||
if [[ -n "$TAG" ]]; then
|
||||
OP_CMD="$OP_CMD --tags=$TAG"
|
||||
fi
|
||||
|
||||
if [[ -n "$VAULT" ]]; then
|
||||
OP_CMD="$OP_CMD --vault=$VAULT"
|
||||
fi
|
||||
|
||||
# Function to colorize the output
|
||||
highlight_match() {
|
||||
local text="$1"
|
||||
local pattern="$2"
|
||||
echo "$text" | grep --color=always -i "$pattern" || echo "$text"
|
||||
}
|
||||
|
||||
# Function to copy to clipboard
|
||||
copy_to_clipboard() {
|
||||
local text="$1"
|
||||
|
||||
if command -v wl-copy &> /dev/null; then
|
||||
echo -n "$text" | wl-copy
|
||||
echo "Copied to clipboard with wl-copy"
|
||||
elif command -v xclip &> /dev/null; then
|
||||
echo -n "$text" | xclip -selection clipboard
|
||||
echo "Copied to clipboard with xclip"
|
||||
elif command -v pbcopy &> /dev/null; then
|
||||
echo -n "$text" | pbcopy
|
||||
echo "Copied to clipboard with pbcopy"
|
||||
else
|
||||
echo "No clipboard utility found. Here's the value:"
|
||||
echo "$text"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function to format and display results
|
||||
display_items() {
|
||||
local items="$1"
|
||||
local count=$(echo "$items" | jq 'length')
|
||||
|
||||
if [[ $count -eq 0 ]]; then
|
||||
echo "No items found matching your search criteria."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Found $count matching items:"
|
||||
|
||||
if [[ "$USE_NUSHELL" == "true" ]]; then
|
||||
# Use Nushell for pretty output
|
||||
echo "$items" | nu -c "open - | select id title category updated vault_id | sort-by title"
|
||||
else
|
||||
# Use jq for formatting
|
||||
echo "$items" | jq -r '
|
||||
["ID", "TITLE", "CATEGORY", "UPDATED"] as $headers |
|
||||
([$headers] +
|
||||
(. | map([.id, .title, .category, .updated[0:10]]))) |
|
||||
.[] | @tsv' | column -t -s $'\t'
|
||||
fi
|
||||
|
||||
if [[ $count -gt 0 ]]; then
|
||||
echo ""
|
||||
select_item "$items"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to select an item and show details or get password
|
||||
select_item() {
|
||||
local items="$1"
|
||||
local count=$(echo "$items" | jq 'length')
|
||||
|
||||
echo "Select an item by number (1-$count) or press Enter to exit:"
|
||||
select opt in $(echo "$items" | jq -r '.[].title'); do
|
||||
if [[ -z "$opt" ]]; then
|
||||
echo "Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
local idx=$((REPLY-1))
|
||||
if [[ $idx -ge 0 && $idx -lt $count ]]; then
|
||||
local item_id=$(echo "$items" | jq -r ".[$idx].id")
|
||||
local item_title=$(echo "$items" | jq -r ".[$idx].title")
|
||||
|
||||
echo "Selected: $item_title (ID: $item_id)"
|
||||
|
||||
if [[ "$GET_PASSWORD" == "true" ]]; then
|
||||
# Get password and copy to clipboard
|
||||
local password=$(op item get "$item_id" --fields password)
|
||||
if [[ -n "$password" ]]; then
|
||||
copy_to_clipboard "$password"
|
||||
else
|
||||
echo "No password field found for this item."
|
||||
|
||||
# Show available fields
|
||||
echo "Available fields:"
|
||||
op item get "$item_id" --format=json | jq -r '.fields[] | select(.id != "notesPlain") | "\(.id): \(.label)"'
|
||||
|
||||
echo "Get a specific field? Enter field ID or press Enter to skip:"
|
||||
read -r field_id
|
||||
|
||||
if [[ -n "$field_id" ]]; then
|
||||
local field_value=$(op item get "$item_id" --fields "$field_id")
|
||||
if [[ -n "$field_value" ]]; then
|
||||
copy_to_clipboard "$field_value"
|
||||
else
|
||||
echo "Field not found or empty."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
elif [[ "$SHOW_DETAIL" == "true" ]]; then
|
||||
# Show detailed information
|
||||
echo "Detailed information:"
|
||||
echo "------------------------------------------------"
|
||||
if [[ -n "$FIELD" ]]; then
|
||||
# Show only the requested field
|
||||
op item get "$item_id" --fields "$FIELD"
|
||||
else
|
||||
# Show all fields
|
||||
if [[ "$USE_NUSHELL" == "true" ]]; then
|
||||
op item get "$item_id" --format=json | nu -c "open - | get fields | where id != 'notesPlain' | sort-by label"
|
||||
else
|
||||
op item get "$item_id" --format=json | jq -r '.fields[] | select(.id != "notesPlain") | "\(.label): \(.value)"'
|
||||
fi
|
||||
fi
|
||||
echo "------------------------------------------------"
|
||||
else
|
||||
# Show basic information
|
||||
op item get "$item_id" --format=json | jq -r '.fields[] | select(.id == "username" or .id == "password" or .id == "notesPlain") | "\(.label): \(.value // "[Hidden]")"'
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Select another item or press Ctrl+C to exit:"
|
||||
else
|
||||
echo "Invalid selection. Please choose a number between 1 and $count."
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Execute search
|
||||
check_dependencies
|
||||
|
||||
if [[ -z "$SEARCH_TERM" && -z "$TAG" && -z "$CATEGORY" ]]; then
|
||||
echo "Error: No search term provided."
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Execute the command and store the results
|
||||
RESULT=$(eval "$OP_CMD")
|
||||
|
||||
# Filter results based on search term
|
||||
if [[ -n "$SEARCH_TERM" ]]; then
|
||||
FILTERED_RESULT=$(echo "$RESULT" | jq --arg term "$SEARCH_TERM" -r '[.[] | select(
|
||||
(.title | ascii_downcase | contains($term | ascii_downcase)) or
|
||||
(.id | ascii_downcase | contains($term | ascii_downcase)) or
|
||||
(.additional_information | ascii_downcase | contains($term | ascii_downcase)) or
|
||||
(.urls != null and (.urls[] | ascii_downcase | contains($term | ascii_downcase))) or
|
||||
(.tags != null and (.tags[] | ascii_downcase | contains($term | ascii_downcase)))
|
||||
)]')
|
||||
else
|
||||
FILTERED_RESULT="$RESULT"
|
||||
fi
|
||||
|
||||
# Display the results
|
||||
display_items "$FILTERED_RESULT"
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue