From df4ccada33502da30fad1a215e12b3ab95d0c516 Mon Sep 17 00:00:00 2001 From: yosh Date: Wed, 3 May 2023 18:29:22 -0400 Subject: [PATCH] initial commit --- README.md | 2 + albumsetup | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++ avalifetch | 87 +++++++++++++++++++++++++++++++++ discogarchive | 53 ++++++++++++++++++++ doasedit | 37 ++++++++++++++ ffrec | 43 ++++++++++++++++ moovcheck | 2 + n | 23 +++++++++ nsxiv-rifle | 41 ++++++++++++++++ pw | 27 ++++++++++ screenshot | 72 +++++++++++++++++++++++++++ stranslate | 53 ++++++++++++++++++++ unityextract | 5 ++ xbps-clean | 16 ++++++ 14 files changed, 594 insertions(+) create mode 100644 README.md create mode 100755 albumsetup create mode 100755 avalifetch create mode 100755 discogarchive create mode 100755 doasedit create mode 100755 ffrec create mode 100755 moovcheck create mode 100755 n create mode 100755 nsxiv-rifle create mode 100755 pw create mode 100755 screenshot create mode 100755 stranslate create mode 100755 unityextract create mode 100755 xbps-clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..f82a861 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# misc scripts +just a bunch of random scripts I use, all which vary in documentation and quality. everything is written in posix shell, but nothing is guaranteed to be 100% posix. all of these are made primarily for my sake with no real intentions of developing for others. diff --git a/albumsetup b/albumsetup new file mode 100755 index 0000000..270ffae --- /dev/null +++ b/albumsetup @@ -0,0 +1,133 @@ +#!/bin/sh +set -euf + +EXT="flac" # default +NL=" +" + +err() { echo "$*" >&2 ; } +die() { err "$*" && exit 1 ; } +clean() { + trap 'exit' INT HUP EXIT + rm -f "$PICTURE" +} + +# wrapper to grab a specific tag from flac/opus/mp3 +grabtag() { + case ${1##*.} in + flac) metaflac --show-tag="$2" "$1" | cut -d '=' -f 2- ;; + opus) opusinfo "$1" | awk -v RS='\n\t' -v FS='=' -v OFS='' "/^$2=/"'{$1=""; print $0}' ;; + mp3) + case "$2" in + ARTIST) id3 -q '%_a' "$1" ;; + ALBUM) id3 -q '%_A' "$1" ;; + TRACKNUMBER) id3 -q '%_###T' "$1" ;; + TITLE) id3 -q '%_t' "$1" ;; + ALBUMARTIST) id3 -2 -q "%|%{TPE2}||%{TXXX:ALBUM ARTIST}|?" "$1" ;; + *) printf 'unknown' ;; + esac + ;; + *) die 'unknown tag used for mp3' + esac +} + +# grab track info, make tracknumber 3-padded just in case for long albums +# (no album has > 999 tracks. I think.) +grabinfo() { + DURATION="$(ffprobe -v quiet -of csv=p=0 -show_entries format=duration "$1")" + ARTIST="$(grabtag "$1" ARTIST)" + ALBUM="$(grabtag "$1" ALBUM)" + TITLE="$(grabtag "$1" TITLE)" + TRACKNUMBER="$(printf '%03d' "$(grabtag "$1" TRACKNUMBER)")" +} + +ffconv() { + IFS=" " + ffmpeg ${VERBOSE--loglevel error} -y -loop 1 -framerate 4 -f image2 -i "$1" ${FULLALBUM:+-safe 0 -f concat} -i "$2" \ + -t "${TOTALTIME:-$DURATION}" \ + -pix_fmt yuv420p \ + ${acopy:--c:a libopus -b:a 256k} \ + -r 4 \ + -b:v 500k \ + -c:v libvpx \ + -cpu-used -5 \ + -deadline realtime \ + "$3" + err "Successfully converted $2" +} + +SONG="" FULLALBUM="" AUTOPIC="" +OUTDIR="/tmp/albumsetup/${PWD##*/}" +while getopts :aovd:e:p:s: OPT; do + case "$OPT" in + a) AUTOPIC=1 ;; # autopic + o) FULLALBUM=1 ;; + v) VERBOSE="" ;; # can use ${var-rep} for this + d) cd "$OPTARG" && OUTDIR="${OUTDIR%/*}/${PWD##*/}" ;; + e) EXT="$OPTARG" ;; + p) tmpimg="$OPTARG" ;; + s) SONG="$OPTARG" && OUTDIR="${OUTDIR%/*}" ;; # individual song + *) die "albumsetup: invalid option: -$OPTARG" ;; + esac +done +shift "$((OPTIND - 1))" + +[ ! -f "$tmpimg" ] && die "Image not specified! This is required even with AUTOPIC!" +[ "$AUTOPIC" ] && [ "$SONG" ] && die "AUTOPIC doesn't make sense in SONG mode!" +[ "$AUTOPIC" ] && [ "$FULLALBUM" ] && die "AUTOPIC doesn't make sense in FULLALBUM mode!" + +mkdir -p "$OUTDIR" + +# convert cover image. it has to be wider than 1:1 so youtube doesn't convert it to a short +# if image is wider than 1:1, just resize height. if not, pad with black +PICTURE="$OUTDIR/ALBUMSETUP_IMG.png" +magick convert "$tmpimg" -resize 1280x720 -background black -gravity center -extent 722x720 "$PICTURE" + +trap 'clean' INT HUP EXIT +[ "$EXT" = "opus" ] && acopy="-c:a copy" # copy audio codec if opus since output codec is opus + +# individual song +if [ "$SONG" ]; then + grabinfo "$SONG" + ffconv "$PICTURE" "$SONG" "$OUTDIR/SONG ${ARTIST%%/*} - ${TITLE%%/*}.webm" # substitution mods are to not create directories +# one continuous video with timestamps +elif [ "$FULLALBUM" ]; then + TOTALTIME=0 # keeping track of timestamps + IFS="$NL" + for f in $(fd -d 1 -e "$EXT"); do + grabinfo "$f" + + # make timestamp + printf '%02d:%02d:%02d - %s\n' \ + "$((${TOTALTIME%%.*} / 3600))" "$((${TOTALTIME%%.*} % 3600 / 60))" "$((${TOTALTIME%%.*} % 60))" \ + "$ARTIST - $TITLE" >> "$OUTDIR/metadata.txt" + # add to total time, but this is as a float remember that + TOTALTIME="$(echo "$TOTALTIME + $DURATION" | bc)" + # build ffmpeg concat metadata + sf="$(printf '%s' "$f" | sed "s/'/'\\\\''/g")" # make safe filename for ffmpeg concat; replace all ' with '\'' + echo "file '${PWD}/$sf'" >> "$OUTDIR/ffmpeg_tracklist.txt" + done + [ ! -f "$OUTDIR/ffmpeg_tracklist.txt" ] && die "No files found!" + ffconv "$PICTURE" "$OUTDIR/tracklist.txt" "$OUTDIR/$ARTIST - $ALBUM.webm" + rm "$OUTDIR/ffmpeg_tracklist.txt" +else # individual tracks for a full album + IFS="$NL" + for f in $(fd -d 1 -e "$EXT"); do + grabinfo "$f" + + # metadata print + printf '%s %s - %s - %s\n' "${TRACKNUMBER:-000}" "${ARTIST:-unknown artist}" "${ALBUM:-unknown album}" "${TITLE:-unknown title}" >> "$OUTDIR/metadata.txt" + # try making auto pic + # if $PIC_AUTO doesn't exist (i.e. trackXXX.(jpg|png), use $PICTURE as fallback + [ "$AUTOPIC" ] && PIC_AUTO="$(fd -e jpg -e png "^track$TRACKNUMBER")" + err "Converting $f" + ffconv "${PIC_AUTO:-$PICTURE}" "$f" "$OUTDIR/$TRACKNUMBER ${ARTIST%%/*} - ${TITLE%%/*}.webm" + done + [ ! -f "$OUTDIR/metadata.txt" ] && die "No files found!" + # sort by correct track numbers then remove track numbers later + sort -o "$OUTDIR/metadata.txt.sorted" "$OUTDIR/metadata.txt" + while read -r line; do + echo "$line" | cut -d ' ' -f 2- + done <"$OUTDIR/metadata.txt.sorted" >"$OUTDIR/metadata.txt" + rm "$OUTDIR/metadata.txt.sorted" +fi diff --git a/avalifetch b/avalifetch new file mode 100755 index 0000000..73747e6 --- /dev/null +++ b/avalifetch @@ -0,0 +1,87 @@ +#!/bin/sh +set -euf + +COLORS="178 245 36 163 239 15" +ASCIIART="$XDG_CONFIG_HOME/neofetch/avali" +GAP=2 + +system_info() { + # use the function "iprint" for everything + # use $(col x) to get an arbitrary 0-255 color + # use $(bold) to bold, $(res) to reset formatting + iprint "$(col 10)$(bold)${USER}$(res)$(col 15)@$(bold)$(col 10)$(uname -n)" + iprint "$(col 7)$(bold)--------------" + iprint "$(col 15)$(bold)OS:$(res)$(col 10) Void Linux" + iprint "$(col 15)$(bold)Kernel:$(res)$(col 11) $(uname -r)" + iprint "$(col 15)$(bold)Shell:$(res)$(col 13) ${SHELL##*/}" + iprint "$(col 15)$(bold)WM:$(res)$(col 7) awesome" + iprint "$(col 15)$(bold)Terminal:$(res)$(col 7) urxvt" +# iprint "$(col 15)$(bold)CPU:$(res)$(col 7) $(cat /proc/cpuinfo | grep -i '^model name' | sort -u | sed -r 's/^model name\t: (.+)/\1/')" + iprint "$(col 15)$(bold)Packages:$(res)$(col 7) $(xbps-query -l | rg -c .)" + iprint "$(col 15)$(bold)Uptime:$(res)$(col 7) $(uptime -p | cut -d ' ' -f 2-)" + iprint "$(col 15)$(bold)Song:$(res)$(col 7) $(mpc -f '%artist% - %title%' current)" + iprint "$(col 7)$(bold)--------------" + iprint "" + iprint "$(col 0)███$(col 1)███$(col 2)███$(col 3)███$(col 4)███$(col 5)███$(col 6)███$(col 7)███" + iprint "$(col 8)███$(col 9)███$(col 10)███$(col 11)███$(col 12)███$(col 13)███$(col 14)███$(col 15)███" +} + +# <-+-+-+-+-+- CONFIGURATION ENDS -+-+-+-+-+-> # + +colres='\033[m' + +process_colors() { +# colindex=1 +# while IFS=" " read -r curcol; do +# colesc="$(tput setaf "$curcol")" +# c$colindex="$colesc" +# colindex="$(($colindex + 1))" +# done <<-EOF +# "$COLORS" +# EOF + c1="$(printf '%b\033[38;5;%sm' "$colres" "$1")" + c2="$(printf '%b\033[38;5;%sm' "$colres" "$2")" + c3="$(printf '%b\033[38;5;%sm' "$colres" "$3")" + c4="$(printf '%b\033[38;5;%sm' "$colres" "$4")" + c5="$(printf '%b\033[38;5;%sm' "$colres" "$5")" + c6="$(printf '%b\033[38;5;%sm' "$colres" "$6")" +} + +process_ascii() { + # get maximum line length + maxlen="$(sed -e 's/\${c[1-6]}//g' "$ASCIIART" | wc -L)" + linecount="$(grep -c '^' "$ASCIIART")" + + # actually do color replacement + final_ascii="$(sed \ + -e "s/\${c1}/$c1/g" \ + -e "s/\${c2}/$c2/g" \ + -e "s/\${c3}/$c3/g" \ + -e "s/\${c4}/$c4/g" \ + -e "s/\${c5}/$c5/g" \ + -e "s/\${c6}/$c6/g" \ + "$ASCIIART")" + + info_padding=$((GAP+maxlen)) +} + +col() { printf "\033[38;5;%sm" "$1"; } +bold() { printf '\033[1m'; } +res() { printf '\033[0m'; } +# reset formatting, move to padding, print line +iprint() { printf "%b%s\n" "\033[0m\033[${info_padding}C" "$1"; } + +print_all() { + tput rmam # disable line wrapping + printf '%s\n' "$final_ascii" + printf '\0337 \033[?25l' # save cursor pos & hide it + printf "\033[%sF" "$linecount" # + system_info + tput smam # enable line wrapping + printf '\0338\n\033[?25h' # restore cursor pos & unhide it +} + +set -f -- $COLORS && set +f +process_colors "$@" +process_ascii +print_all diff --git a/discogarchive b/discogarchive new file mode 100755 index 0000000..75d16c1 --- /dev/null +++ b/discogarchive @@ -0,0 +1,53 @@ +#!/bin/sh +set -euf + +BN="${0##*/}" +NL=' +' + +errecho() { + >&2 echo "$*" +} + +fail() { + errecho "error: $BN: $*" + exit 1 +} + +clean() { + rm -f "$FILE" + rm -f "$tmpfile" +} + +FILE="/tmp/$(printf '%s' "$1" | cut -d '/' -f 3).html" +BASEURL="${1%/*}" +trap 'clean' INT HUP QUIT EXIT +curl -s "$1" -o "$FILE" + +tmpfile="$(mktemp -u)" +# albums and tracks +for type in album track; do + while IFS= read -r url; do + curl -s -o "$tmpfile" "$url" + artist="$(pup 'script[type="application/ld+json"]' 'text{}' <"$tmpfile" | jq -r '.byArtist.name')" + name="$(pup 'script[type="application/ld+json"]' 'text{}' <"$tmpfile" | jq -r '.name')" + if [ "$(pup 'span:contains("name your price"), button:contains("Free Download")' <"$tmpfile")" ]; then + eval 'contained_'"$type"'s="$artist - $name
${NL}${contained_'"$type"'s:-}"' + echo "CONTAINED $type: $artist - $name" + else + eval 'uncontained_'"$type"'s="$artist - $name
${NL}${uncontained_'"$type"'s:-}"' + echo "UNCONTAINED $type: $artist - $name" + fi + done <<-EOF + $(rg -e '"(/'"$type"'/.+)"' -or "$BASEURL"'$1' "$FILE") + EOF +done + +if [ "${uncontained_albums:-}" ] || [ "${uncontained_tracks:-}" ]; then + printf '
Uncontained Releases
\n%s\n%s\n
Contained Releases
\n%s\n%s\n' \ + "${uncontained_albums:+$uncontained_albums
}" "${uncontained_tracks:+SINGLES
$uncontained_tracks
}" \ + "${contained_albums:+$contained_albums}" "${contained_tracks:+
SINGLES
$NL$contained_tracks}" +else + printf '
Contained Releases
\n%s\n%s\n' \ + "${contained_albums:+$contained_albums}" "${contained_tracks:+
SINGLES
$NL$contained_tracks}" +fi diff --git a/doasedit b/doasedit new file mode 100755 index 0000000..e88bc39 --- /dev/null +++ b/doasedit @@ -0,0 +1,37 @@ +#!/bin/sh +set -f + +ercho() { echo "$*" >&2 ; } +error() { ercho "$*" && exit 1 ; } +TMPDIR="${TMPDIR:-/tmp}" +ed="${VISUAL:-vi}" + +clean() { + [ -f "$tmpfile" ] && rm -f "$tmpfile" +} + +[ "$(whoami)" = "root" ] && error "Cannot be run as root!" +[ -z "$1" ] && error "No files provided!" + +trap 'clean' 1 INT HUP KILL EXIT + +for f; do + [ ! -f "$f" ] && ercho "File $f is not a regular file, is not accessible by the user, or does not exist. Skipping..." && continue + tmpfile="$(mktemp -t doasedit_XXXXXXXX)" || error "Cannot make temp file for $f! Exiting..." + + cp -fp "$f" "$tmpfile" || error "Cannot copy file $f! Exiting..." + ercho "$ed '$f'" + + $ed "$tmpfile" || error "Exit code != 0 by editor. Exiting..." + + cmp "$f" "$tmpfile" >/dev/null 2>&1 + ec=$? + if [ $ec -eq 1 ]; then + if [ ! -w "$f" ]; then doas mv -f "$tmpfile" "$f"; else mv -f "$tmpfile" "$f" && echo "$f didn't need root perms!"; fi + elif [ $ec -eq 0 ]; then + ercho "File not changed, skipping..." + else + ercho "Problem running diff on $f! Skipping..." + fi + rm -f "$tmpfile" +done diff --git a/ffrec b/ffrec new file mode 100755 index 0000000..127f1d3 --- /dev/null +++ b/ffrec @@ -0,0 +1,43 @@ +#!/bin/sh +set -eu + +OUTFILE="$HOME/Pictures/Screenshots/$(date +"%Y-%m-%d_%H-%M-%S").mp4" + +LOCKFILE="/tmp/ffrec.pid" +[ -s "$LOCKFILE" ] && xargs kill < "$LOCKFILE" && notify-send "Recording saved to $OUTFILE" && rm -f "$LOCKFILE" && exit 0 + +errecho() { + >&2 echo "$@" +} + +usage() { + errecho "usage: ${0##*/} [-h] [-a SOURCE] [-r FPS]" + errecho + errecho " -h: show this message and exit" + errecho " -a: record audio from SOURCE (only with PA / pipewire-pulse) (set to \"\" for alsa output)" + errecho " -r: set recording framerate to FPS (default: 60)" +} + +while getopts :ha:r: OPT; do + case "$OPT" in + h) usage; exit 0;; + a) AUDIO="-f pulse -i ${OPTARG:-alsa_output.pci-0000_30_00.6.analog-stereo.monitor}" ;; + r) FPS="$OPTARG" ;; + *) errecho "ffrec: invalid option: -$OPTARG"; exit 1 ;; + esac +done + +IFS=" " read -r SIZE OFFSET <<-EOF + $(hacksaw -f "%wx%h %x,%y") +EOF +[ -z "$SIZE" ] && exit 1 # if slop was cancelled don't record + +( + flock -n 9 + set -f + ffmpeg -thread_queue_size 512 -f x11grab -show_region 1 -framerate "${FPS:-60}" -s "$SIZE" -i "$DISPLAY.0+$OFFSET" ${AUDIO:-} -c:v libx264 -crf 21 -preset:v fast "$OUTFILE" & + set +f + echo "$!" > "$LOCKFILE" + notify-send "Recording Started!" + wait +) 9>"$LOCKFILE" diff --git a/moovcheck b/moovcheck new file mode 100755 index 0000000..8d9b840 --- /dev/null +++ b/moovcheck @@ -0,0 +1,2 @@ +#!/bin/sh +ffprobe -v trace -i "$1" 2>&1 | rg -e type:\'mdat\' -e type:\'moov\' diff --git a/n b/n new file mode 100755 index 0000000..5518f1f --- /dev/null +++ b/n @@ -0,0 +1,23 @@ +#!/bin/sh +# nnn previewer wrapper +set -euf + +if [ "${NNNLVL:-0}" -ge 1 ]; then + echo "don't nest nnn!" && exit +fi + +[ "${TMUX:-}" ] && exec nnn + +vars="NNN_BATTHEME=Dracula +NNN_BATSTYLE=full +NNN_TERMINAL=urxvt +" +IFS=' +' +varstring="" +for env in $vars; do + export "${env?}" + varstring="$varstring -e $env" +done; unset IFS + +tmux new $varstring -s nnn -c exec nnn "${PWD:-"$HOME"}" || tmux new-window -t nnn: nnn "${PWD:-"$HOME"}" \; a -t nnn diff --git a/nsxiv-rifle b/nsxiv-rifle new file mode 100755 index 0000000..a6c4e6a --- /dev/null +++ b/nsxiv-rifle @@ -0,0 +1,41 @@ +#!/bin/sh + +TMPDIR="${XDG_RUNTIME_DIR}" +tmp="$TMPDIR/nsxiv_rifle_$$" + +is_img_extension() { + rg -i '\.(jpe?g|png|gif|svg|webp|tiff|heif|avif|ico|bmp|jxl)$' +} + +listfiles() { + fd . -L -d 1 -t f "$1" | + is_img_extension | sort | tee "$tmp" +} + +open_img() { + file="$1"; shift; + # only go through listfiles() if the file has a valid img extension + if echo "$file" | is_img_extension >/dev/null 2>&1; then + trap 'rm -f "$tmp"' EXIT + count="$(listfiles "${file%/*}" | rg -nF "$file")" + fi + if [ -n "$count" ]; then + nsxiv -i -n "${count%%:*}" "$@" -- < "$tmp" + else + # fallback incase file didn't have a valid extension, or we couldn't + # find it inside the list + nsxiv "$@" -- "$file" + fi +} + +[ "$1" = '--' ] && shift +case "$1" in + "") echo "Usage: ${0##*/} PICTURES" >&2; exit 1 ;; + /*) open_img "$1" ;; + "~"/*) open_img "$HOME/${1#"~"/}" ;; + trash:///*) + trash_dir="${XDG_DATA_HOME:-$HOME/.local/share}/Trash/files" + open_img "${trash_dir}$(uri2path "$1")" -N "nsxiv_trash" + ;; + *) open_img "$PWD/$1" ;; +esac diff --git a/pw b/pw new file mode 100755 index 0000000..6116fa3 --- /dev/null +++ b/pw @@ -0,0 +1,27 @@ +#!/bin/sh +set -euf + +PASSAGE_DIR="${PASSAGE_DIR:-$HOME/.passage/store}" +PASSAGE_IDENTITIES_FILE="${PASSAGE_IDENTITIES_FILE:-$HOME/.passage/identities}" +PASSAGE_ROOT="${PASSAGE_DIR%/*}" +STORE_LOCK="$PASSAGE_ROOT/store.tar.age" + +lock() { + [ -d "$PASSAGE_DIR" ] && agetar -e -R "$PASSAGE_DIR/.age-recipients" -o "$STORE_LOCK" "$PASSAGE_DIR" && rm -rf "$PASSAGE_DIR" +} + +unlock() { + [ -f "$STORE_LOCK" ] && agetar -d -i "$PASSAGE_ROOT/identities" -o "$PASSAGE_ROOT" "$STORE_LOCK" && rm -rf "$STORE_LOCK" +} + +while getopts :lu OPT; do + case "$OPT" in + l) lock ;; + u) unlock ;; + *) exit 1 ;; + esac +done + +[ -d "$PASSAGE_DIR" ] && STATE=UNLOCKED + +echo "Password store is ${STATE:-LOCKED}" diff --git a/screenshot b/screenshot new file mode 100755 index 0000000..57f9051 --- /dev/null +++ b/screenshot @@ -0,0 +1,72 @@ +#!/bin/sh +set -ef + +OUTFILE="$HOME/Pictures/Screenshots/$(date +"%Y-%m-%d_%H-%M-%S").jxl" # output file template, change as needed +DMENUOPTS="-c -z 128 -bw 2" # custom dmenu options + +clean() { + [ "$nsxiv_pid" ] && kill "$nsxiv_pid" + [ "$tmpfreeze" ] && rm -f "$tmpfreeze" + rm -f "$tmpfp" +} + +save() { + cjxl "$tmpfp" -d 0.0 "$OUTFILE" && notify-send -u low "$OUTFILE" + exit 0 +} + +savemenu() { printf 'save?' | dmenu $DMENUOPTS -l 1 && save; } + +choose() { + while true; do + case "$(printf "save\nedit\nscan\nupload" | dmenu $DMENUOPTS -l 4)" in + save) save ;; + edit) + h1="$(md5sum "$tmpfp")" + gimp -n "$tmpfp" + h2="$(md5sum "$tmpfp")" + [ "$h1" != "$h2" ] && save # changed, save + ;; + scan) + zdata="$(zbarimg -1 "$tmpfp")" || zdata="error: scan failed with exit code $?" + export zdata + urxvt -g 75x25 -e sh -c 'printf "%s\n" "${zdata#*:}" | vim -' & + printf '%s\n' "${zdata#*:}" + ;; + upload) + owo -u "$tmpfp" | xclip -sel clipboard && notify-send "uploaded and copied successfully!" || notify-send "upload error! you should probably save the image" + ;; + *) break ;; + esac + done +} + +ss() { + [ "$ssopts" = "-g" ] && ssopts="$(hacksaw -f "-i %i -g %g")" + shotgun $ssopts "$tmpfp" + [ "$nsxiv_pid" ] && kill "$nsxiv_pid" && nsxiv_pid="" # unfreeze + xclip -selection clipboard -t image/png < "$tmpfp" # copy screenshot + choose +} + +freeze() { + tmpfreeze="$(mktemp -t screenshot_freeze_XXXX.png)" + shotgun "$tmpfreeze" + nsxiv -b -N SCREENSHOT_FREEZE "$tmpfreeze" & + nsxiv_pid=$! + # window manager makes it fullscreen (yippee!) +} + +tmpfp="$(mktemp -t screenshot_XXXX.png)" +trap 'clean' INT HUP EXIT + +while getopts :srwf OPT; do + case "$OPT" in + s) ssopts="-s" ;; # screen + r) ssopts="-g" ;; # region + w) ssopts="-i $(xdotool getactivewindow)" ;; # active window + f) freeze ;; # freeze screen, only useful with -r + *) echo "invalid option: -$OPTARG" && exit 1 ;; + esac +done +ss diff --git a/stranslate b/stranslate new file mode 100755 index 0000000..54daa7a --- /dev/null +++ b/stranslate @@ -0,0 +1,53 @@ +#!/bin/sh + +# DEFAULT OPTIONS +INSTANCE="https://translate.tiekoetter.com/" +ENGINE="google" +FLANG="auto" +TLANG="en" + +BN="${0##*/}" + +errecho() { + >&2 echo "$@" +} + +fail() { + errecho "error: $BN: $*" + exit 1 +} + +usage() { + errecho \ +"usage: $BN [-h] [-i INSTANCE] [-e ENGINE] [-f LANG] [-t LANG] TEXT +translate text using simplytranslate + + -h show this help + -i choose simplytranslate instance + default: \"$INSTANCE\" + -e use ENGINE to translate + default: \"$ENGINE\" + -f translate from LANG + default: \"$FLANG\" + -t translate to LANG + default: \"$TLANG\"" + exit 0 +} + +# Read options +while getopts :hi:f:t: OPT; do + case "$OPT" in + h) usage ;; + i) INSTANCE="$OPTARG" ;; + e) ENGINE="$OPTARG" ;; + f) FLANG="$OPTARG" ;; + t) TLANG="$OPTARG" ;; + *) fail "unknown option: -$OPTARG. run $BN -h to see all options" ;; + esac +done +shift $((OPTIND - 1)) + +[ "$*" ] || set -- "$(cat /dev/stdin)" +[ "$*" ] || usage + +curl -s "${INSTANCE}/api/translate?engine=${ENGINE}&from=${FLANG}&to=${TLANG}&text=$(jq -rn --arg x "$*" '$x|@uri')" | jq -r '."translated-text"' diff --git a/unityextract b/unityextract new file mode 100755 index 0000000..9996c66 --- /dev/null +++ b/unityextract @@ -0,0 +1,5 @@ +#!/bin/sh +set -euf + +tar xf "$1" +fd '^asset$' -x sh -c 'SRC="$1"; DESTFILE="$(cat "${SRC%/*}/pathname")"; mkdir -p "UNITYEXTRACT/${DESTFILE%/*}"; mv "$SRC" "UNITYEXTRACT/$DESTFILE"' sh diff --git a/xbps-clean b/xbps-clean new file mode 100755 index 0000000..38b4ef8 --- /dev/null +++ b/xbps-clean @@ -0,0 +1,16 @@ +#!/bin/sh + +while getopts :d OPT; do + case "$OPT" in + d) DEL=1 ;; + *) echo "invalid option: -$OPTARG" && exit 1 ;; + esac +done + +for x in /var/cache/xbps/*.xbps; do + xbps-query "$(xbps-uhelper binpkgver "$x")" 1>/dev/null 2>&1 + if [ $? -eq 2 ]; then + echo "${x%.*}" + [ "$DEL" ] && rm "${x%.*}".* + fi +done