Blog/Pinnwand
From Forza's ramblings
Pinnwand[edit | edit source]
Pinnwand is a simple and efficient paste service that allows you to share text snippets easily. Unlike popular paste services that may include ads, tracking cookies, or other third-party scripts, a self-hosted Pinnwand instance can provide a private and ad-free alternative.
The Pinnwand source code is available from https://github.com/supakeen/pinnwand
Paste from shell command line[edit | edit source]
I wrote a small bash script gist.sh to make it easy to post small files to my own Pinnwand instance at https://gist.tnonline.net.
Sample usage[edit | edit source]
To paste a single file with syntax highlighting:
./gist.sh -l python file.py
Paste URL: https://gist.tnonline.net/ABYXA Removal URL: https://gist.tnonline.net/remove/K4AV3F33WXJRSUJBQDGUS43TTMADHT
To paste multiple files with a specified expiry:
./gist.sh -e 1hour file1.txt file2.txt
To paste the output from a command:
dmesg | ./gist.sh -l kmsg
To list supported languages for syntax highlighting:
./gist.sh --lexers
"asc": "ASCII armored", "asn1": "ASN.1", "actionscript": "ActionScript", "actionscript3": "ActionScript 3", "ada": "Ada", "agda": "Agda", "aheui": "Aheui", "alloy": "Alloy", "ambienttalk": "AmbientTalk", "ampl": "Ampl", "ng2": "Angular2", "apacheconf": "ApacheConf", "applescript": "AppleScript", "arduino": "Arduino", "arrow": "Arrow", ...
gist.sh[edit | edit source]
#!/bin/bash
# SPDX-License-Identifier: GPL-3.0-or-later
# Base URL of the Pinnwand instance
PINNWAND_BASE_URL="https://gist.tnonline.net/api/v1"
PASTE_URL="${PINNWAND_BASE_URL}/paste"
LEXER_URL="${PINNWAND_BASE_URL}/lexer"
# Default options
expiry="1day"
lexer="text"
# Function to show help information
show_help() {
local s
s=$(basename "$0")
cat <<END
Usage: $s [options] [file1 file2 ...]
Options:
-e, --expiry <expiry> Set the expiry time for the paste (e.g., 1day, 1hour).
Default is '1day' if not specified.
-l, --lexer <lexer> Specify the lexer to use for syntax highlighting.
--lexers List all available lexers in 'name : description' format.
-h, --help Show this help message and exit.
Examples:
$s -e 1hour -l python file1 file2
$s --lexers
dmesg | $s -l kmsg
END
exit 0
}
# Function to check if a file or input is binary
is_binary() {
local input="$1"
if [[ -f "$input" ]]; then
# If input is a file, check directly with file command
[[ "$(file --mime-encoding -b -L "$input")" == "binary" ]]
else
# If input is from stdin, use grep to check for binary content
grep -qI . <<< "$input"
return $? # Return 0 for text, non-zero for binary
fi
}
# Function to post content to Pinnwand
post_to_pinnwand() {
local expiry="$1"
local lexer="$2"
shift 2
local files=("$@")
# Prepare files array for JSON
files_json="["
if [[ "${#files[@]}" -gt 0 ]]; then
# Add each file to the JSON array
for file in "${files[@]}"; do
if [[ -f "$file" ]]; then
# Check if the file is binary
if is_binary "$file"; then
echo "Error: $file is a binary file. Only text files are allowed."
exit 1
fi
content=$(<"$file" jq -Rs .) # Read and JSON-encode file content
files_json+="{\"name\":\"$(basename "$file")\",\"lexer\":\"$lexer\",\"content\":$content},"
else
echo "File not found: $file"
exit 1
fi
done
else
# If no files were provided, read from stdin
stdin_content=$(cat | jq -Rs .) # Read and JSON-encode stdin content
# Check if stdin content is binary
if is_binary "$stdin_content"; then
echo "Error: Input from stdin is binary. Only text content is allowed."
exit 1
fi
files_json+="{\"name\":\"stdin\",\"lexer\":\"$lexer\",\"content\":$stdin_content},"
fi
# Remove trailing comma and close array
files_json="${files_json%,}]"
response=$(curl -s -X POST "$PASTE_URL" \
-H "Content-Type: application/json" \
-d '{"expiry":"'"$expiry"'","files":'"$files_json"'}' )
# Extract link and removal URLs from the response
link=$(echo "$response" | jq -r '.link')
removal=$(echo "$response" | jq -r '.removal')
# Check if the response contains a URL
if [[ "$response" == null ]]; then
echo "Error: Could not create paste"
exit 1
else
echo "Paste URL: $link"
echo "Removal URL: $removal"
fi
}
# Function to list available lexers
list_lexers() {
curl -s "$LEXER_URL" | jq -r '.'
exit 0
}
# Parse command line options
while [ "$#" -gt 0 ]; do
case $1 in
-e|--expiry)
expiry="$2"
shift 2
;;
-l|--lexer)
lexer="$2"
shift 2
;;
--lexers)
list_lexers
;;
-h|--help)
show_help
;;
*)
break
;;
esac
done
# Remaining arguments are assumed to be files
files=("$@")
# Post content from provided files or stdin
post_to_pinnwand "$expiry" "$lexer" "${files[@]}"