This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

tools.jellyseekrr: add Jellyseerr search and request tool

+191
+17
tools/jellyseekrr/flake-module.nix
··· 1 + { self, ... }: 2 + { 3 + perSystem = 4 + { pkgs, ... }: 5 + { 6 + packages.jellyseekrr = pkgs.writeShellApplication { 7 + name = "jellyseekrr"; 8 + runtimeInputs = with pkgs; [ 9 + self.packages.${pkgs.system}.menu 10 + self.packages.${pkgs.system}.pass 11 + curl 12 + jq 13 + ]; 14 + text = builtins.readFile ./jellyseekrr.sh; 15 + }; 16 + }; 17 + }
+174
tools/jellyseekrr/jellyseekrr.sh
··· 1 + #!/usr/bin/env bash 2 + set -euo pipefail 3 + 4 + # Configuration 5 + JELLYSEERR_URL="https://flox.lassul.us" 6 + 7 + # Get API key from pass or environment 8 + JELLYSEERR_API_KEY="${JELLYSEERR_API_KEY:-$(pass show www/flox.lassul.us/api_key 2>/dev/null | tr -d '\n' || true)}" 9 + 10 + # Check if API key is available 11 + if [[ -z "$JELLYSEERR_API_KEY" ]]; then 12 + echo "Error: Could not retrieve API key" >&2 13 + echo "Set JELLYSEERR_API_KEY environment variable or ensure 'pass show www/flox.lassul.us/api_key' works" >&2 14 + exit 1 15 + fi 16 + 17 + # Get search query from command line or prompt 18 + if [[ $# -eq 0 ]]; then 19 + echo "Usage: jellyseerr <search_query>" >&2 20 + echo "Example: jellyseerr 'The Matrix'" >&2 21 + exit 1 22 + fi 23 + 24 + search_query="$*" 25 + 26 + # Create a temporary cookie jar 27 + COOKIE_JAR=$(mktemp) 28 + trap 'rm -f "$COOKIE_JAR"' EXIT 29 + 30 + # Function to authenticate and get session 31 + authenticate() { 32 + # Try to authenticate with the API key 33 + local auth_response 34 + auth_response=$(curl -s \ 35 + -c "$COOKIE_JAR" \ 36 + -H "Content-Type: application/json" \ 37 + -d "{\"email\":\"api\",\"password\":\"$JELLYSEERR_API_KEY\"}" \ 38 + "${JELLYSEERR_URL}/api/v1/auth/local") 39 + 40 + if ! echo "$auth_response" | jq -e '.id' > /dev/null 2>&1; then 41 + echo "Warning: Authentication failed, trying direct API key approach" >&2 42 + return 1 43 + fi 44 + return 0 45 + } 46 + 47 + # Function to search for content 48 + search_content() { 49 + local query="$1" 50 + 51 + # First try with API key header 52 + local response 53 + response=$(curl -s \ 54 + -H "X-Api-Key: $JELLYSEERR_API_KEY" \ 55 + -H "Content-Type: application/json" \ 56 + -H "Accept: application/json" \ 57 + "${JELLYSEERR_URL}/api/v1/search?query=$(printf '%s' "$query" | jq -sRr @uri)") 58 + 59 + # If that fails with cookie error, try with session 60 + if echo "$response" | grep -q "cookie.*required"; then 61 + authenticate || { 62 + echo "Failed to authenticate" >&2 63 + exit 1 64 + } 65 + response=$(curl -s \ 66 + -b "$COOKIE_JAR" \ 67 + -H "Content-Type: application/json" \ 68 + -H "Accept: application/json" \ 69 + "${JELLYSEERR_URL}/api/v1/search?query=$(printf '%s' "$query" | jq -sRr @uri)") 70 + fi 71 + 72 + echo "$response" 73 + } 74 + 75 + # Function to request content 76 + request_content() { 77 + local media_type="$1" 78 + local media_id="$2" 79 + local title="$3" 80 + 81 + local request_data 82 + if [[ "$media_type" == "movie" ]]; then 83 + request_data=$(jq -n \ 84 + --arg mediaType "movie" \ 85 + --argjson mediaId "$media_id" \ 86 + '{ 87 + mediaType: $mediaType, 88 + mediaId: $mediaId 89 + }') 90 + else 91 + # For TV shows, request all seasons 92 + request_data=$(jq -n \ 93 + --arg mediaType "tv" \ 94 + --argjson mediaId "$media_id" \ 95 + '{ 96 + mediaType: $mediaType, 97 + mediaId: $mediaId, 98 + seasons: "all" 99 + }') 100 + fi 101 + 102 + local response 103 + # Try with API key first, then with cookies if that fails 104 + response=$(curl -s \ 105 + -X POST \ 106 + -H "X-Api-Key: $JELLYSEERR_API_KEY" \ 107 + -H "Content-Type: application/json" \ 108 + -d "$request_data" \ 109 + "${JELLYSEERR_URL}/api/v1/request") 110 + 111 + # If that fails with cookie error, use session cookies 112 + if echo "$response" | grep -q "cookie.*required"; then 113 + response=$(curl -s \ 114 + -X POST \ 115 + -b "$COOKIE_JAR" \ 116 + -H "Content-Type: application/json" \ 117 + -d "$request_data" \ 118 + "${JELLYSEERR_URL}/api/v1/request") 119 + fi 120 + 121 + if echo "$response" | jq -e '.id' > /dev/null 2>&1; then 122 + echo "✓ Successfully requested: $title" 123 + else 124 + echo "✗ Failed to request: $title" 125 + echo "Response: $response" >&2 126 + fi 127 + } 128 + 129 + # Search for content 130 + echo "Searching for: $search_query" >&2 131 + search_results=$(search_content "$search_query") 132 + 133 + # Check if search was successful 134 + if ! echo "$search_results" | jq -e '.results' > /dev/null 2>&1; then 135 + echo "Error: Search failed or no results found" >&2 136 + echo "Response: $search_results" >&2 137 + exit 1 138 + fi 139 + 140 + # Parse results and create menu options 141 + menu_options=$(echo "$search_results" | jq -r ' 142 + .results[] | 143 + select(.mediaType == "movie" or .mediaType == "tv") | 144 + [ 145 + .id, 146 + .mediaType, 147 + .title // .name, 148 + (.releaseDate // .firstAirDate // "Unknown" | split("-")[0]), 149 + (.overview // "No description available" | .[0:100] + if length > 100 then "..." else "" end) 150 + ] | 151 + "\(.[0])|\(.[1])|\(.[2]) (\(.[3])) - \(.[4])" 152 + ') 153 + 154 + if [[ -z "$menu_options" ]]; then 155 + echo "No movies or TV shows found for: $search_query" >&2 156 + exit 1 157 + fi 158 + 159 + # Show menu and get selection 160 + selected=$(echo "$menu_options" | menu) 161 + 162 + if [[ -z "$selected" ]]; then 163 + echo "No selection made" >&2 164 + exit 0 165 + fi 166 + 167 + # Parse selection 168 + media_id=$(echo "$selected" | cut -d'|' -f1) 169 + media_type=$(echo "$selected" | cut -d'|' -f2) 170 + title=$(echo "$selected" | cut -d'|' -f3) 171 + 172 + # Request the selected content 173 + echo "Requesting: $title" >&2 174 + request_content "$media_type" "$media_id" "$title"