dotfiles/.local/bin/pastebin_client.sh
2025-05-28 18:33:04 +02:00

490 lines
13 KiB
Bash
Executable File

#!/bin/bash
API_URL="https://paste.priet.us"
TOKEN_FILE="$HOME/.pastebin_token"
load_token() {
[[ -f "$TOKEN_FILE" ]] && TOKEN=$(cat "$TOKEN_FILE") || TOKEN=""
}
save_token() {
echo "$TOKEN" > "$TOKEN_FILE"
}
authenticate() {
local username="$1" password="$2"
response=$(curl -s -X POST "$API_URL/api/token" \
-H "Content-Type: application/json" \
-d '{"username": "'$username'", "password": "'$password'"}')
if echo "$response" | grep -q 'token'; then
TOKEN=$(echo "$response" | jq -r '.token')
save_token
echo "Authentication successful. Token saved."
else
echo "Authentication failed: $(echo "$response" | jq -r '.error')"
exit 1
fi
}
list_users() {
load_token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
response=$(curl -s -H "Authorization: Bearer $TOKEN" "$API_URL/api/users")
error_msg=$(echo "$response" | jq -r '.error // empty')
if [[ -n "$error_msg" ]]; then
echo "Error: $error_msg"
return 1
fi
usernames=$(echo "$response" | jq -r '.users[]')
echo "$usernames"
}
remove_gps_metadata() {
local paste_id="$1"
load_token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
if [[ -z "$paste_id" ]]; then
echo "Usage: $0 remove_gps <paste_id>"
return 1
fi
response=$(curl -s -X POST "$API_URL/api/removegps" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"paste_id\": $paste_id}")
success=$(echo "$response" | jq -r '.success // empty')
if [[ "$success" == "true" ]]; then
echo "✅ GPS metadata successfully removed from paste ID $paste_id"
else
error_msg=$(echo "$response" | jq -r '.error // empty')
echo "❌ Error: $error_msg"
fi
}
edit_paste() {
local paste_id="$1"
load_token
# Chequear token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
if [[ -z "$paste_id" ]]; then
echo "Usage: $0 edit <paste_id>"
return 1
fi
# 1. Descargar contenido JSON del paste
echo "Fetching current content of paste $paste_id..."
response=$(curl -s -H "Authorization: Bearer $TOKEN" \
"$API_URL/paste/$paste_id/json")
# Checar error
error_msg=$(echo "$response" | jq -r '.error // empty')
if [[ -n "$error_msg" ]]; then
echo "Error: $error_msg"
return 1
fi
# 2. Extraer el contenido, filename, etc.
current_content=$(echo "$response" | jq -r '.content // empty')
paste_filename=$(echo "$response" | jq -r '.filename // empty')
paste_language=$(echo "$response" | jq -r '.language // empty')
# 3. Decidir la extensión local:
# a) tratar de inferirla de paste_filename
# b) si no hay, usar language
# c) fallback a "txt"
# Extraer extensión del filename, si existe
extension="txt"
if [[ -n "$paste_filename" ]]; then
# e.g. "myscript.py" -> ".py"
ext_from_name="${paste_filename##*.}" # todo lo que viene después de la última.
if [[ "$ext_from_name" != "$paste_filename" ]]; then
extension="$ext_from_name"
fi
elif [[ -n "$paste_language" ]]; then
# Una pequeña tabla de mapeo básico
case "$paste_language" in
python) extension="py" ;;
javascript|js) extension="js" ;;
typescript|ts) extension="ts" ;;
java) extension="java" ;;
c) extension="c" ;;
cpp|c++) extension="cpp" ;;
bash|shell) extension="sh" ;;
html) extension="html" ;;
css) extension="css" ;;
json) extension="json" ;;
sql) extension="sql" ;;
*) extension="txt" ;;
esac
fi
# 4. Crear archivo temporal con esa extensión
temp_file=$(mktemp "/tmp/paste_${paste_id}_XXXXXX.${extension}")
# 5. Guardar el contenido en el archivo y abrir editor
echo "$current_content" > "$temp_file"
"${EDITOR:-nano}" "$temp_file"
# 6. Leer el contenido editado
new_content=$(cat "$temp_file")
if [[ -z "$new_content" ]]; then
echo "No content provided. Aborting."
rm -f "$temp_file"
return 1
fi
# 7. Convertir a JSON con jq -Rs '.'
new_content_json=$(echo "$new_content" | jq -Rs '.')
# 8. Enviar PUT /api/paste/<paste_id> con el nuevo contenido
update_response=$(curl -s -X PUT "$API_URL/api/paste/$paste_id" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"content":'"$new_content_json"'}')
# 9. Mostrar resultado
msg=$(echo "$update_response" | jq -r '.message // .error // empty')
if [[ -n "$msg" ]]; then
echo "$msg"
else
echo "$update_response"
fi
# 10. Limpieza
rm -f "$temp_file"
}
unshare_paste() {
local paste_id="$1" username="$2"
load_token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
if [[ -z "$paste_id" || -z "$username" ]]; then
echo "Error: Paste ID and username are required."
return 1
fi
response=$(curl -s -X POST "$API_URL/api/paste/$paste_id/unshare" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"username": "'$username'"}')
if echo "$response" | grep -q '"message"'; then
echo "$response" | jq -r '.message'
else
echo "Error: $(echo "$response" | jq -r '.error')"
fi
}
share_paste() {
local paste_id="$1"
local username="$2"
local can_edit_input="${3:-false}" # Por defecto, no se permite editar
load_token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
# Validación de argumentos
if [[ -z "$paste_id" || -z "$username" ]]; then
echo "Usage: share_paste <paste_id> <username> [can_edit (true|false)]"
return 1
fi
# Validar que can_edit sea 'true' o 'false'
if [[ "$can_edit_input" != "true" && "$can_edit_input" != "false" ]]; then
echo "Error: can_edit must be 'true' or 'false'."
return 1
fi
# Convertir la entrada can_edit a booleano JSON
if [[ "$can_edit_input" == "true" ]]; then
can_edit_json=true
else
can_edit_json=false
fi
# Construir el JSON de manera segura usando jq
json_data=$(jq -n --arg username "$username" --argjson can_edit "$can_edit_json" \
'{username: $username, can_edit: $can_edit}')
# Verificar que json_data es válido
if [[ -z "$json_data" ]]; then
echo "Error: Failed to construct JSON data."
return 1
fi
# Realizar la solicitud POST al endpoint y capturar la respuesta y el código HTTP
response=$(curl -s -w "\n%{http_code}" -X POST "$API_URL/api/paste/$paste_id/share" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$json_data")
# Separar el cuerpo de la respuesta y el código de estado
http_body=$(echo "$response" | sed '$d')
http_code=$(echo "$response" | tail -n1)
# Manejar la respuesta según el código de estado
if [[ "$http_code" == "200" ]]; then
echo "$http_body" | jq
elif [[ "$http_code" == "400" || "$http_code" == "403" || "$http_code" == "404" || "$http_code" == "500" ]]; then
echo "$http_body" | jq -r '.error // .message'
else
echo "Unexpected HTTP code: $http_code"
echo "$http_body"
fi
}
list_shared_with_others() {
load_token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
response=$(curl -s -H "Authorization: Bearer $TOKEN" "$API_URL/api/shared_with_others")
echo "$response" | jq
}
list_shared_with_me() {
load_token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
response=$(curl -s -H "Authorization: Bearer $TOKEN" "$API_URL/api/shared_with_me")
echo "$response" | jq
}
list_favorites() {
load_token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
response=$(curl -s -H "Authorization: Bearer $TOKEN" "$API_URL/api/favorites")
echo "$response" | jq
}
download() {
local paste_id="$1"
load_token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
# Solicitar el archivo y guardar las cabeceras en un archivo temporal
response=$(curl -s -w "%{http_code}" -D headers.tmp -o "paste_${paste_id}.tmp" \
-H "Authorization: Bearer $TOKEN" "$API_URL/api/paste/$paste_id/download")
# Extraer el código HTTP del final de la respuesta
http_code=$(echo "$response" | tail -n1)
if [[ "$http_code" -eq 200 ]]; then
# Extraer el nombre del archivo del encabezado "Content-Disposition"
filename=$(grep -i "Content-Disposition" headers.tmp | grep -o 'filename="[^"]*"' | sed 's/filename=//' | tr -d '"')
if [[ -z "$filename" ]]; then
# Si no se encuentra el encabezado, usar un nombre genérico
file_extension=$(file --mime-type -b "paste_${paste_id}.tmp" | awk -F'/' '{print $2}')
filename="paste_${paste_id}.${file_extension}"
fi
mv "paste_${paste_id}.tmp" "$filename"
echo "Paste $paste_id downloaded to $filename"
elif [[ "$http_code" -eq 403 ]]; then
echo "Error: You do not have permission to download paste $paste_id."
rm -f "paste_${paste_id}.tmp"
elif [[ "$http_code" -eq 404 ]]; then
echo "Error: Paste $paste_id not found."
rm -f "paste_${paste_id}.tmp"
else
echo "Failed to download paste $paste_id (HTTP code: $http_code)"
rm -f "paste_${paste_id}.tmp"
fi
# Limpieza
rm -f headers.tmp
}
download_favorites() {
load_token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
response=$(curl -s -H "Authorization: Bearer $TOKEN" "$API_URL/api/favorites")
echo "$response" | jq -r '.[] | @base64' | while read paste; do
paste_id=$(echo "$paste" | base64 --decode | jq -r '.id')
download "$paste_id"
done
}
create_paste() {
# local lang="$1"
local expire="${1:-yes}"
local private="${2:-no}" # ✅ Nuevo parámetro opcional, por defecto "no"
echo "Enter the content for the paste (Ctrl+D to finish):"
content=$(cat)
[[ -z "$content" ]] && { echo "Error: Paste content cannot be empty."; exit 1; }
response=$(echo "$content" | curl -s -X POST "$API_URL/paste" \
-H "Authorization: Bearer $TOKEN" \
-F "c=@-" \
-F "expire=$expire" \
$( [[ "$private" == "yes" ]] && echo "-F private=true" ) ) # ✅ Se envía "private=true" solo si es necesario
echo "$response" | jq -r '.url // .error'
}
upload_file() {
local file="$1"
local expire="${2:-yes}"
local private="${3:-no}"
[[ ! -f "$file" ]] && { echo "Error: File not found."; exit 1; }
response=$(curl -s -X POST "$API_URL/paste" \
-H "Authorization: Bearer $TOKEN" \
-F "c=@$file" \
-F "expire=$expire" \
$( [[ "$private" == "yes" ]] && echo "-F private=true" ) ) # ✅ Se envía "private=true" solo si es necesario
echo "$response" | jq -r '.url // .error'
}
view_paste() {
local paste_id="$1"
response=$(curl -s "$API_URL/paste/$paste_id/json" \
-H "Authorization: Bearer $TOKEN")
echo "$response" | jq -r '.content // .error'
}
list_pastes() {
response=$(curl -s "$API_URL/pastes" -H "Authorization: Bearer $TOKEN")
echo "$response" | jq
}
delete_paste() {
local paste_id="$1"
response=$(curl -s -X DELETE "$API_URL/paste/$paste_id" \
-H "Authorization: Bearer $TOKEN")
echo "$response"
}
view_raw() {
local paste_id="$1"
response=$(curl -s "$API_URL/paste/$paste_id/raw" \
-H "Authorization: Bearer $TOKEN")
echo "$response"
}
register_user() {
local username="$1" password="$2"
response=$(curl -s -X POST "$API_URL/register" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"username": "'$username'", "password": "'$password'"}')
echo "$response"
}
details() {
response=$(curl -s -X GET "$API_URL/user/details" \
-H "Authorization: Bearer $TOKEN")
echo "$response" | jq
}
search_pastes() {
local query="$1"
response=$(curl -s -X GET "$API_URL/pastes/search?q=$query" \
-H "Authorization: Bearer $TOKEN")
echo "$response" | jq
}
add_to_favorites() {
local paste_id="$1"
load_token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
response=$(curl -s -X POST "$API_URL/api/paste/$paste_id/favorite" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json")
echo "$response"
}
remove_from_favorites() {
local paste_id="$1"
load_token
if [[ -z "$TOKEN" ]]; then
echo "Error: No token found. Please authenticate first."
return 1
fi
response=$(curl -s -X POST "$API_URL/api/paste/$paste_id/unfavorite" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json")
echo "$response"
}
load_token
case "$1" in
login) authenticate "$2" "$3" ;;
edit) edit_paste "$2" ;;
shared_with_others) list_shared_with_others ;;
shared_with_me) list_shared_with_me ;;
download) download "$2" ;;
list_favorites) list_favorites ;;
remove_gps) remove_gps_metadata "$2" ;;
favorite) add_to_favorites "$2" ;;
unfavorite) remove_from_favorites "$2" ;;
create) create_paste "$2" "$3" ;;
upload) upload_file "$2" "$3" "$4" ;;
view) view_paste "$2" ;;
share) share_paste "$2" "$3" "$4" ;;
unshare) unshare_paste "$2" "$3" ;;
list) list_pastes ;;
delete) delete_paste "$2" ;;
view_raw) view_raw "$2" ;;
register) register_user "$2" "$3" ;;
details) details ;;
search) search_pastes "$2" ;;
*) echo "Usage: $0 {login|create|upload|view|list|delete|view_raw|register|details|search|favorite|unfavorite|shared_with_others|shared_with_me|share|unshare|remove_gps}" ;;
esac