diff options
Diffstat (limited to '.local/bin')
34 files changed, 752 insertions, 265 deletions
diff --git a/.local/bin/awesome b/.local/bin/awesome new file mode 120000 index 0000000..3da827c --- /dev/null +++ b/.local/bin/awesome @@ -0,0 +1 @@ +../share/wrapper.sh
\ No newline at end of file diff --git a/.local/bin/bl b/.local/bin/bl index da1980e..ee71504 100755 --- a/.local/bin/bl +++ b/.local/bin/bl @@ -29,13 +29,25 @@ main() case "$1" in inc) - xbacklight -inc ${2:-5} + brightnessctl set +${2:-5}% notify="Brightness increased to $(brightness_level)%" ;; dec) - xbacklight -dec ${2:-5} + if [ $(brightness_level) -lt $(( ${2:-5} + 1 )) ] + then + brightnessctl set 1 + else + brightnessctl set ${2:-5}%- + fi + notify="Brightness lowered to $(brightness_level)%" ;; + set) + [ -z "$2" ] && usage && exit 1 + + brightnessctl set $2% + notify="Brightness set to $(brightness_level)%" + ;; esac notify-send -n 57492 -s -t 2 -i "$(brightness_icon)" "Backlight" "$notify" @@ -43,7 +55,7 @@ main() brightness_level() { - xbacklight -get + awk "BEGIN { printf(\"%d\", ($(brightnessctl get) / $(brightnessctl max)) * 100) }" } brightness_icon() @@ -61,8 +73,16 @@ usage() cat <<EOF Usage: ${0##*/} -h + ${0##*/} inc [level] + ${0##*/} dec [level] + ${0##*/} set <level> + +Alter the backlight intensity. -Nondescript +Subcommands: + inc Increase the volume by level, defaults to 5. + dec Decrease the volume by level, defaults to 5. + set Set the volume to level. Options: -h Show this help text and exit. diff --git a/.local/bin/count b/.local/bin/count new file mode 100755 index 0000000..cc02a71 --- /dev/null +++ b/.local/bin/count @@ -0,0 +1,44 @@ +#!/bin/sh + +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. + +main() +{ + # Handle opts + while getopts ":h" opt + do + case "$opt" in + h) usage && exit 0 ;; + *) + printf "Invalid option passed: %s\n" "$OPTARG" >&2 + ;; + esac + done + + shift $(( OPTIND - 1 )) + + cat - | sort | uniq -c | sort -h +} + +usage() +{ + cat <<EOF +Usage: + ${0##*/} -h + +Count occurrences of unique lines. + +Options: + -h Show this help text and exit. +EOF +} + +main "$@" diff --git a/.local/bin/dmenu b/.local/bin/dmenu index 78cdf52..6c1494b 100755 --- a/.local/bin/dmenu +++ b/.local/bin/dmenu @@ -1,8 +1,20 @@ #!/usr/bin/env sh -if ! command -v rofi > /dev/null -then - exec /usr/bin/dmenu "$@" -fi +main() { + if [ -n "$WAYLAND_DISPLAY" ] + then + exec fuzzel --dmenu "$@" + fi -exec rofi -dmenu "$@" + if [ -n "$DISPLAY" ] + then + if command -v rofi > /dev/null + then + exec rofi -dmenu "$@" + fi + + exec /usr/bin/dmenu "$@" + fi +} + +main "$@" diff --git a/.local/bin/downloadgemist b/.local/bin/downloadgemist new file mode 100755 index 0000000..d690ba8 --- /dev/null +++ b/.local/bin/downloadgemist @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 + +import argparse +import requests +import sys + +# Handle arguments +argparser = argparse.ArgumentParser( + description = "Command line utility to interact with downloadgemist.nl", +) +argparser.add_argument("url") + +args = argparser.parse_args() + +# Make the actual HTTP request +form = requests.post( + "https://www.downloadgemist.nl/core/hyperbridge.php", + data={ + "mode": "initiate", + "link": args.url, + "options": '{"size":"large","download_tt888":true}', + }, +) + +# Make sure the response is json +if form.headers.get("Content-Type").lower() != "application/json": + print("oh no") + sys.exit(1) + +json = form.json() + +print(form.json()) + +# Handle any errors +if json["status"] == 1: + print(form.json()["error"]) + sys.exit(form.json()["status"]) + +# Write the downloaded file +video = requests.get(json["file"]) + +open(json["filename"], "wb").write(video.content) diff --git a/.local/bin/firefox b/.local/bin/firefox index dde1929..3da827c 100755..120000 --- a/.local/bin/firefox +++ b/.local/bin/firefox @@ -1,47 +1 @@ -#!/bin/sh - -# This program is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the Free -# Software Foundation, either version 3 of the License, or (at your option) any -# later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more -# details. - -readonly BINS=" - /usr/bin/firefox - /usr/bin/firefox-bin -" - -main() -{ - require_exe "firejail" - - for bin in $BINS - do - [ -x "$bin" ] || continue - - exec firejail --profile="$HOME/.local/etc/firejail/firefox.profile" -- \ - "$bin" --profile "$HOME/.config/firefox" "$@" - done - - printf "No underlying executable found for %s:\n" "${0##*/}" >&2 - - for bin in $BINS - do - printf "\t%s\n" "$bin" >&2 - done -} - -require_exe() -{ - if ! command -v "$1" > /dev/null 2>&1 - then - printf "Missing required executable %s\n" "$1" - exit 3 - fi -} - -main "$@" +../share/wrapper.sh
\ No newline at end of file diff --git a/.local/bin/get-focussed-monitor b/.local/bin/get-focussed-monitor deleted file mode 100755 index 4d7bbd4..0000000 --- a/.local/bin/get-focussed-monitor +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env raku - -use v6.d; - -sub MAIN ( - #Bool:D :$shell = False, - Bool:D :$coords = False, -) { - my @xrandr = shell('xrandr | grep -w connected', :out).out.slurp.lines; - my %monitors; - - my $mouse = shell('xdotool getmouselocation', :out).out.slurp.trim ~~ m/ - 'x:' $<x> = [ \d+ ] - \s* - 'y:' $<y> = [ \d+ ] - /; - - for @xrandr -> $monitor { - my $match = $monitor ~~ m/ - $<width> = [ \d+ ] - 'x' - $<height> = [ \d+ ] - '+' - $<x> = [ \d+ ] - '+' - $<y> = [ \d+ ] - /; - - next unless $match<x> ≤ $mouse<x> ≤ ($match<x> + $match<width>); - next unless $match<y> ≤ $mouse<y> ≤ ($match<y> + $match<height>); - - say qq[MONITOR="{$monitor.words.first}"]; - - if ($coords) { - say qq[W="{$match<width>}"]; - say qq[H="{$match<height>}"]; - say qq[X="{$match<x>}"]; - say qq[Y="{$match<y>}"]; - } - - last; - } -} diff --git a/.local/bin/gittab b/.local/bin/gittab deleted file mode 100755 index 5ffd5f9..0000000 --- a/.local/bin/gittab +++ /dev/null @@ -1,87 +0,0 @@ -#! /usr/bin/env perl6 - -use v6.d; - -constant TABDIR = $*HOME.add('.local/etc/gittab/tabs'); -constant TABCONF = $*HOME.add('.local/etc/gittab/basedirs'); - -#| Update managed git repositories -multi sub MAIN ( - #| A list of targets to update. - *@targets, -) { - @targets = TABDIR.dir.map(*.basename) unless @targets; - - for @targets -> $target { - my $tab = find-tab($target); - - note "No gittab for target '$target'" unless $tab; - - my $basedir = get-basedir($target); - - mkdir($basedir) unless $basedir.d; - - for $tab.lines.grep(!*.starts-with("#")) { - my ($name, $repo, $branch) = $_.words; - - if (!$basedir.add($name).d) { - chdir $basedir; - run « git clone --single-branch --branch "$branch" --depth 1 "$repo" "$name" »; - } - - chdir $basedir.add($name); - run « git checkout "$branch" »; - run « git pull "$repo" "$branch" »; - } - } -} - -#| List managed git repositories -multi sub MAIN ( - Bool:D :$list!, -) { - my @tabs = TABDIR.dir.map(*.basename).sort; - my $longest = @tabs.map(*.chars).sort.tail; - - for @tabs { - "%-{$longest}s %s\n".printf($_, get-basedir($_)); - } -} - -sub find-tab ( - Str:D $name, -) { - my @attempts = - $name, - $name ~ 'tab', - ; - - for @attempts { - my $fh = TABDIR.add($_); - - return $fh if $fh.f; - } - - Nil; -} - -sub get-basedir ( - Str:D $tab, -) { - state %basedirs; - - if (!%basedirs && TABCONF.e) { - TABCONF - .lines - .grep(!*.starts-with('#')) - .map({ - my ($tab, $basedir) = $_.words; - - %basedirs{$tab} = $basedir.IO; - }) - } - - return $*HOME unless %basedirs{$tab}:exists; - - $*HOME.add(%basedirs{$tab}); -} diff --git a/.local/bin/herbstluftwm b/.local/bin/herbstluftwm new file mode 120000 index 0000000..3da827c --- /dev/null +++ b/.local/bin/herbstluftwm @@ -0,0 +1 @@ +../share/wrapper.sh
\ No newline at end of file diff --git a/.local/bin/hyprland-switch-tag b/.local/bin/hyprland-switch-tag new file mode 100755 index 0000000..06840c9 --- /dev/null +++ b/.local/bin/hyprland-switch-tag @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +# Pascal Jaeger <pascal.jaeger@leimstift.de> + +# utils +green="\033[0;32m" +red="\033[0;31m" +blue="\033[0;34m" +nocolor="\033[0m" + +#util functions +check() { + command -v "$1" 1>/dev/null +} + +ok() { + echo -e "[$green $nocolor] $*" +} + +err() { + echo -e "[$red $nocolor] $*" +} +optional() { + echo -e "[$blue $nocolor] $*" +} + +notify() { + # shellcheck disable=SC2015 + check notify-send && { + notify-send "$@" + } || { + echo "$@" + } +} + +checkUtils() { + # shellcheck disable=SC2015 + check grep && ok "grep" || err "grep" + # shellcheck disable=SC2015 + check grep && ok "cut" || err "cut" + # shellcheck disable=SC2015 + check notify-send && ok "notify-send (Optional)" || optional "notify-send (Optional)" + exit +} + +basicChecks() { + check hyprctl || { + notify "Seriously mate!!" "Start Hyprland before this script" + exit 1 + } + pgrep -x Hyprland &>/dev/null || { + notify "Make Sure Hyprland Session is running." + exit 1 + } +} + +help() { + cat <<EOF + This is a bash script to move arbitrary workspace to arbritrary monitor and to swap workspaces between + monitors if the desired workspace is already active on a monitor for Hyprland using hyprctl. + + flags: + -h: Displays This help menu + -c: Checks for all dependencies + + Usage: try_swap_workspace [WORKSPACE] + bind = ALT,1,exec, /path/to/try_swap_workspace/binary 1 + (where the last 1 is the workspace that should be shown on the currently active monitor) + +EOF +} + +getArgs() { + while [ "$#" -gt 0 ]; do + case "$1" in + -h | --help) + help + exit 0 + ;; + -c) + checkUtils + ;; + (*[!0-9]*) + # contains non-numbers + help + echo "" + echo "Wrong argument given" + exit 1 + ;; + *) + # only nubers left, so good + switch_or_swap "$1" + ;; + esac + shift + done +} + + +#variables +mon_wrkspcs=() + +get_active_mon() { + echo $(($(hyprctl monitors | grep 'focused' | grep -n 'yes' | cut -c1)-1)) +} + +get_workspaces_array() { + local workspaces + workspaces=$(hyprctl monitors | grep 'active workspace' | cut -f3 -d' ') + SAVEIFS=$IFS + IFS=$'\n' + mon_wrkspcs=($workspaces) + IFS=$SAVEIFS +} + +# first argument: workspace to switch to +# second argument: monitor to switch workspace on +switch_workspace() { + local target_wrkspc=$1 + local target_mon=$2 + hyprctl dispatch moveworkspacetomonitor "$target_wrkspc" "$target_mon" + hyprctl dispatch workspace "$target_wrkspc" +} +# first argument: monitor the workspace should go to +# second argument: monitor the workspace is currently displayed on +swap_workspace() { + local target_mon=$1 + local source_mon=$2 + hyprctl dispatch swapactiveworkspaces "$target_mon" "$source_mon" +} + +# first argument: workspace to switch to active monitor +switch_or_swap() { + target_mon=$(get_active_mon) + target_wrkspc=$1 + get_workspaces_array + # check if the workspace is currently displayed on another monitor + local currently_active_on_mon=-1 + for (( i=0; i<${#mon_wrkspcs[@]}; i++ )) + do + if [[ "$target_wrkspc" == "${mon_wrkspcs[$i]}" ]]; then + currently_active_on_mon=$i + fi + done + if [[ $currently_active_on_mon -lt 0 ]]; then + # workspace is not active on any monitor, do a normal switch + ok "switching workspace $target_wrkspc to monitor $target_mon" + switch_workspace "$target_wrkspc" "$target_mon" + else + # workspace is already active on other monitor, swap workspaces between monitor + ok "swapping workspaces between $target_mon to monitor $currently_active_on_mon" + swap_workspace "$target_mon" "$currently_active_on_mon" + fi +} + +main() { + basicChecks + getArgs "$@" +} + +main "$@" diff --git a/.local/bin/import-pape b/.local/bin/import-pape new file mode 100755 index 0000000..b72c169 --- /dev/null +++ b/.local/bin/import-pape @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +readonly PAPEDIR="$HOME/pictures/wallpapers" + +main() { + for s in "$@" + do + local format="$(identify -format "%m" "$s" | awk '{ print(tolower($0)) }')" + local resolution="$(identify -format "%wx%h" "$s")" + local hash="$(sha1sum "$s" | awk '{ print $1 }')" + local destination="$PAPEDIR/$resolution/$hash.$format" + + mkdir -pv -- "$PAPEDIR/$resolution" + printf "Importing %s to %s\n" "$s" "$destination" + mv -- "$s" "$destination" + done +} + +main "$@" diff --git a/.local/bin/ipass b/.local/bin/ipass index deef05f..4f555e4 100755 --- a/.local/bin/ipass +++ b/.local/bin/ipass @@ -1,19 +1,51 @@ #! /usr/bin/env sh -main() -{ +main() { cd -- "$HOME/.password-store" || exit 1 - file=$(find ./* -type f | sed 's-^\./--' | sed 's-\.gpg$--' | dmenu) - dmenu_exit=$? + if [ -n "$WAYLAND_DISPLAY" ] + then + file="$(pass_list | fuzzel -d)" + pass_get "$file" | wl-copy + + notify "Copied $file to clipboard!" + exit 0 + fi - if [ "$dmenu_exit" -ne 0 ] + if [ -n "$DISPLAY" ] then - exit 2 + file="$(pass_list | dmenu)" + pass_get "$file" | xdotool type --file - + dmenu_exit=$? + + if [ "$dmenu_exit" -ne 0 ] + then + notify "Error typing $file" + exit 2 + fi + + notify "Typing $file" + + exit 0 fi - pass show "$file" | head -n 1 | perl -pe 'chomp' | xdotool type --file - - notify-send -i "dialog-password" "ipass" "$file" + notify "No graphical environment detected" +} + +pass_list() { + find ./* -type f \ + | sed 's-^\./--' \ + | sed 's-\.gpg$--' +} + +pass_get() { + pass show "$1" \ + | head -n 1 \ + | perl -pe 'chomp' +} + +notify() { + notify-send -i "dialog-password" "ipass" "$*" } main "$@" diff --git a/.local/bin/irc b/.local/bin/irc new file mode 120000 index 0000000..3da827c --- /dev/null +++ b/.local/bin/irc @@ -0,0 +1 @@ +../share/wrapper.sh
\ No newline at end of file diff --git a/.local/bin/jellyfin b/.local/bin/jellyfin new file mode 120000 index 0000000..3da827c --- /dev/null +++ b/.local/bin/jellyfin @@ -0,0 +1 @@ +../share/wrapper.sh
\ No newline at end of file diff --git a/.local/bin/krokify b/.local/bin/krokify new file mode 100755 index 0000000..a01c1f6 --- /dev/null +++ b/.local/bin/krokify @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +import argparse +import base64 +import sys +import zlib + +def main(): + arg_parser = argparse.ArgumentParser( + prog='krokify', + description='Turn a given file into a kroki link', + ) + arg_parser.add_argument("file", default="-", help="Path to the file to krokify, or - to read from stdin") + arg_parser.add_argument("-f", "--format", default="svg", help="Which output format to use") + arg_parser.add_argument("-s", "--service", required=True, help="Which back-end service to use") + arg_parser.add_argument("-u", "--base-url", default="https://kroki.tyil.nl", help="The base URL of the Kroki server") + + args = arg_parser.parse_args() + + if args.file == "-": + stream = sys.stdin + else: + stream = open(args.file, "r") + + url = base64.urlsafe_b64encode(zlib.compress(stream.read().encode('utf-8'), 9)).decode('ascii') + + print(f"{args.base_url}/{args.service}/{args.format}/{url}") + +if __name__ == "__main__": + main() diff --git a/.local/bin/kubectl-rageclean-pod b/.local/bin/kubectl-rageclean-pod new file mode 100755 index 0000000..bbd3ba7 --- /dev/null +++ b/.local/bin/kubectl-rageclean-pod @@ -0,0 +1,17 @@ +#!/usr/bin/env sh + +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. + +main() { + kubectl delete pod --force --grace-period=0 "$@" +} + +main "$@" diff --git a/.local/bin/kubectl-secret b/.local/bin/kubectl-secret new file mode 100755 index 0000000..ab2e924 --- /dev/null +++ b/.local/bin/kubectl-secret @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 + +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. + +import argparse +import base64 +import sys + +import ruamel.yaml +import ruamel.yaml.scalarstring + +def main(): + argparser = argparse.ArgumentParser(description="Encode or decode Kubernetes Secrets.") + argparser.add_argument("mode", help="Mode of operation, either encode or decode.", choices=["encode", "decode"]) + argparser.add_argument("path", help="Path to the file to operate on. If set to -, STDIN will be used instead.", default="-", nargs="?") + + args = argparser.parse_args() + yaml = ruamel.yaml.YAML() + + # Deduce whether to read from STDIN or open a file handle to a given path + if args.path == "-": + buffer = sys.stdin + else: + buffer = open(args.path) + + # Load the manifest + manifest = yaml.load(buffer.read()) + + # Handle any known potential issues + if not "kind" in manifest: + print("No kind in manifest", file=sys.stderr) + return 3 + + if manifest["kind"] != "Secret": + print("Not a secret", file=sys.stderr) + return 4 + + if not "data" in manifest: + manifest["data"] = {} + + # Call appropriate function with the manifest + manifest = globals()["secret_" + args.mode](manifest) + + # Write the processed manifest back as yaml + yaml.dump(manifest, sys.stdout) + + return 0 + +def secret_decode(manifest): + for key in manifest["data"].keys(): + # Decode the data + manifest["data"][key] = base64.b64decode(manifest["data"][key]).decode("utf-8") + + # Turn this element into a block quoted string if there are newlines + if "\n" in manifest["data"][key]: + manifest["data"][key] = ruamel.yaml.scalarstring.LiteralScalarString(manifest["data"][key]) + + return manifest + +def secret_encode(manifest): + for key in manifest["data"].keys(): + # Encode the data + manifest["data"][key] = base64.b64encode(str(manifest["data"][key]).encode("utf-8")).decode("utf-8") + + return manifest + +if __name__ == '__main__': + sys.exit(main()) diff --git a/.local/bin/kubectl-shell b/.local/bin/kubectl-shell new file mode 100755 index 0000000..781edfa --- /dev/null +++ b/.local/bin/kubectl-shell @@ -0,0 +1,57 @@ +#!/bin/sh + +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. + +main() +{ + # Handle opts + while getopts ":hi:t:" opt + do + case "$opt" in + h) usage && exit 0 ;; + i) DOCKER_IMAGE="$OPTARG" ;; + t) DOCKER_TAG="$OPTARG" ;; + *) + printf "Invalid option passed: %s\n" "$OPTARG" >&2 + ;; + esac + done + + shift $(( OPTIND - 1 )) + + [ -z "$DOCKER_IMAGE" ] && DOCKER_IMAGE="alpine" + [ -z "$DOCKER_TAG" ] && DOCKER_TAG="latest" + + kubectl run "shell-$(uuidgen)" \ + --image "$DOCKER_IMAGE:$DOCKER_TAG" \ + --restart=Never \ + --rm \ + --stdin \ + --tty \ + "$@" \ + -- /bin/sh +} + +usage() +{ + cat <<EOF +Usage: + ${0##*/} -h + +Shorthand to spawn a single pod with an interactive shell into your Kubernetes +cluster. + +Options: + -h Show this help text and exit. +EOF +} + +main "$@" diff --git a/.local/bin/kubecontext b/.local/bin/kubectx index ac99869..ac99869 100755 --- a/.local/bin/kubecontext +++ b/.local/bin/kubectx diff --git a/.local/bin/localmail b/.local/bin/localmail index ef6833e..fcf3284 100755 --- a/.local/bin/localmail +++ b/.local/bin/localmail @@ -22,7 +22,7 @@ use App::Localmail; # I've been at this crossroads before. This is the cpan command to run when # Perl updates... # -# cpan -f -i Data::UUID Sys::Hostname::FQDN YAML::XS +# cpan -f -i Data::UUID Sys::Hostname::FQDN YAML::XS MIME::Base64 Authen::SASL sub main (@args) { my $action = shift @args; @@ -159,7 +159,7 @@ sub send ($config, @args) { $current->{server}, Port => $port, SSL => $current->{ssl} // 0, - Timeout => $current->{timeout} // 5, + Timeout => $current->{timeout} // 30, Hello => Sys::Hostname::FQDN::fqdn(), Debug => 1, ); diff --git a/.local/bin/media-import b/.local/bin/media-import new file mode 100755 index 0000000..a1a99b2 --- /dev/null +++ b/.local/bin/media-import @@ -0,0 +1,53 @@ +#!/bin/bash + +main() { + # Show help + if (( $# < 2 )) + then + echo "You need help" + return 2 + fi + + # Set the paths + local basedir="${MEDIA_BASEDIR:-/var/media}" + local mediadir="$basedir/$1" ; shift + + # Ask for confirmation through a keypress + printf "Going to import %d URIs to %s...\n" "$#" "$mediadir" + read -s -n1 + + # Loop over all given args + for uri in "$@" + do + case "$uri" in + http://*) import_http "$mediadir" "$uri" ;; + https://*) import_http "$mediadir" "$uri" ;; + *) import_local "$mediadir" "$uri" ;; + esac + done +} + +import_http() { + local dest="$1" ; shift + local uri="$1" ; shift + local temp="$(mktemp)" + + wget -c -O "$temp" "$uri" + + local output="$(import_local "$dest" "$temp" | awk '{ print $NF }')" + + printf "%s -> %s\n" "$uri" "$output" +} + +import_local() { + local dest="$1" ; shift + local uri="$1" ; shift + local hash="$(sha1sum "$uri" | awk '{ print $1 }')" + local ext="$(identify "$uri" | awk '{ print tolower($2) }')" + local out="$dest/$hash.$ext" + + mv -- "$uri" "$out" + printf "%s -> %s\n" "$uri" "$out" +} + +main "$@" diff --git a/.local/bin/mpv b/.local/bin/mpv new file mode 120000 index 0000000..3da827c --- /dev/null +++ b/.local/bin/mpv @@ -0,0 +1 @@ +../share/wrapper.sh
\ No newline at end of file diff --git a/.local/bin/mscrot b/.local/bin/mscrot index 3848aaa..fedd0d9 100755 --- a/.local/bin/mscrot +++ b/.local/bin/mscrot @@ -3,4 +3,4 @@ p="~/pictures/scrot" cmd="mv \$f ${p} && notify-send \"Screenshot\" \"Saved to ${p}/\$f\"" -scrot -mz multi-%Y%m%d%H%M%S.png -e "${cmd}" +scrot -m multi-%Y%m%d%H%M%S.png -e "${cmd}" diff --git a/.local/bin/open b/.local/bin/open index 068af10..9877708 100755 --- a/.local/bin/open +++ b/.local/bin/open @@ -58,8 +58,10 @@ proto cmd ($ --> Str) { * } # working purposes. multi sub cmd (HttpUrl $t where { $_.hostname.ends-with('gitlab.com') && $_.path[0].?fc eq 'mintlab' }) { "chromium '$t'" } +multi sub cmd (HttpUrl $t where { $_.hostname.ends-with('gitlab.com') && $_.path[0].?fc eq 'xxllnc' }) { "chromium '$t'" } multi sub cmd (HttpUrl $t where *.hostname.ends-with('atlassian.net')) { "chromium '$t'" } multi sub cmd (HttpUrl $t where *.hostname.ends-with('aws.amazon.com')) { "chromium '$t'" } +multi sub cmd (HttpUrl $t where *.hostname.ends-with('awsapps.com')) { "chromium '$t'" } multi sub cmd (HttpUrl $t where *.hostname.ends-with('google.com')) { "chromium '$t'" } multi sub cmd (HttpUrl $t where *.hostname.ends-with('slack.com')) { "chromium '$t'" } multi sub cmd (HttpUrl $t where *.hostname.ends-with('zaaksysteem.net')) { "chromium '$t'" } @@ -68,22 +70,28 @@ multi sub cmd (HttpUrl $t where *.hostname.ends-with('zaaksysteem.nl')) { "chrom # Rewrite bad site to good site my @not-twitter = < - nitter.42l.fr - nitter.eu - nitter.fdn.fr - nitter.namazso.eu - nitter.nixnet.services - nitter.pussthecat.org - nitter.tedomum.net - nitter.unixfox.eu + nitter.mnus.de + twitter.alt.tyil.nl twitter.lurkmore.com >; -multi sub cmd (HttpUrl $t is copy where *.hostname eq "twitter.com") { callwith(URL.new(|$t.Hash, hostname => @not-twitter.pick())) } +my @not-reddit = < + reddit.alt.tyil.nl +>; + +my @not-youtube = < + youtube.alt.tyil.nl +>; + +multi sub cmd (HttpUrl $t is copy where *.hostname eq "twitter.com") { cmd(URL.new(|$t.Hash, hostname => @not-twitter.pick())) } multi sub cmd (HttpUrl $t is copy where *.hostname eq "instagram.com") { callwith(URL.new(|$t.Hash, hostname => 'brap.top', path => $t.path.unshift('u'))) } multi sub cmd (HttpUrl $t is copy where *.hostname eq "www.instagram.com") { callwith(URL.new(|$t.Hash, hostname => 'brap.top', path => $t.path.unshift('u'))) } +multi sub cmd (HttpUrl $t is copy where *.hostname.ends-with("reddit.com")) { callwith(URL.new(|$t.Hash, hostname => @not-reddit.pick())) } + +multi sub cmd (HttpUrl $t is copy where *.hostname.ends-with("youtube.com")) { callwith(URL.new(|$t.Hash, hostname => @not-youtube.pick())) } + # All other URLs should be opened with the preferred browser. multi sub cmd (HttpUrl $t) { "%*ENV<BROWSER> '$t'" } diff --git a/.local/bin/signal b/.local/bin/signal index 3dc73e2..3da827c 120000 --- a/.local/bin/signal +++ b/.local/bin/signal @@ -1 +1 @@ -../lib/cmd-wrapper/wrapper.sh
\ No newline at end of file +../share/wrapper.sh
\ No newline at end of file diff --git a/.local/bin/sscrot b/.local/bin/sscrot index 2d4c049..3e218d5 100755 --- a/.local/bin/sscrot +++ b/.local/bin/sscrot @@ -5,4 +5,4 @@ cmd="mv \$f ${p} && notify-send \"Screenshot\" \"Saved to ${p}/\$f\"" eval "$(get-focussed-monitor --coords)" -scrot -a $X,$Y,$W,$H -z screen-%Y%m%d%H%M%S.png -e "${cmd}" +scrot -a $X,$Y,$W,$H screen-%Y%m%d%H%M%S.png -e "${cmd}" diff --git a/.local/bin/ssln b/.local/bin/ssln new file mode 100755 index 0000000..546107d --- /dev/null +++ b/.local/bin/ssln @@ -0,0 +1,26 @@ +#!/usr/bin/env perl + +use strict; +use utf8; +use warnings; + +my $cert = ""; +my $count = 0; + +# Loop over STDIN to get the nth certificate +while (<STDIN>) { + # Append current line to potential cert + $cert .= $_; + + # Check for end of certificate + if ($_ =~ /^\-+END(\s\w+)?\sCERTIFICATE\-+$/) { + # Print out the cert if this is the index we're looking for + if (grep(/^$count$/, @ARGV)) { + print $cert; + } + + # Reset potential cert + $cert = ""; + $count++; + } +} diff --git a/.local/bin/ta b/.local/bin/ta index 3d364fa..200aeec 100755 --- a/.local/bin/ta +++ b/.local/bin/ta @@ -1,13 +1,16 @@ -#!/usr/bin/env sh +#!/bin/sh -t="tmux -2 -f ${HOME}/.config/tmux/conf -u" +tmux="tmux -2 -f ${HOME}/.config/tmux/conf -u" +session="$(hostname -s)" -if [ -z "$1" ] +if [ "$1" ] then - session=$(hostname -s) -else - session=$(hostname -s)/$1 + session="$session/$1" fi -${t} attach -t "${session}" || ${t} new-session -s "${session}" +if tmux has-session -t "$session" 2>/dev/null +then + exec $tmux attach -t "$session" +fi +exec $tmux new-session -s "$session" diff --git a/.local/bin/notify-send b/.local/bin/todo index 8dc67a0..4d4df99 100755 --- a/.local/bin/notify-send +++ b/.local/bin/todo @@ -10,18 +10,15 @@ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more # details. +readonly TODOTXT="$HOME/documents/todo.txt" + main() { # Handle opts - while getopts ":a:hi:n:st:" opt + while getopts ":h" opt do case "$opt" in - a) app=$OPTARG ;; h) usage && exit 0 ;; - i) icon=$OPTARG ;; - n) id=$OPTARG ;; - s) silent=1 ;; - t) timeout=$OPTARG ;; *) printf "Invalid option passed: %s\n" "$OPTARG" >&2 ;; @@ -30,34 +27,22 @@ main() shift $(( OPTIND - 1 )) - [ $# -lt 1 ] && usage && exit 1 - - if [ -z "$id" ] + if [ ! -f "$TODOTXT" ] then - id=$(awk -v min=10 -v max=10000 'BEGIN { srand(); print int(min+rand() * (max-min+1)) }') + printf "%s\n" "No todo.txt found at $TODOTXT" >&2 + return 3 fi - gdbus call \ - --session \ - --dest org.freedesktop.Notifications \ - --object-path /org/freedesktop/Notifications \ - --method org.freedesktop.Notifications.Notify \ - "$app" \ - "$id" \ - "$icon" \ - "$1" \ - "$2" \ - "[]" \ - "{}" \ - "$((${timeout:-10} * 1000))" \ - > /dev/null - - if [[ -z "$silent" ]] + if [ "$#" -lt 1 ] then - printf "%d\n" "$id" + cat "$TODOTXT" + return 0 fi - exit 0 + meta="$(date +%F)" + + printf "%s %s gtd:inbox\n" "$meta" "$*" + printf "%s %s gtd:inbox\n" "$meta" "$*" >> "$TODOTXT" } usage() @@ -66,7 +51,7 @@ usage() Usage: ${0##*/} -h -Nondescript +Add an entry to the todo list. Options: -h Show this help text and exit. diff --git a/.local/bin/updot b/.local/bin/updot new file mode 100755 index 0000000..f0179ad --- /dev/null +++ b/.local/bin/updot @@ -0,0 +1,63 @@ +#!/bin/sh + +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. + +main() +{ + DOTFILES_REMOTE="origin" + DOTFILES_BRANCH="master" + + # Handle opts + while getopts ":h" opt + do + case "$opt" in + b) DOTFILES_BRANCH="$OPTARG" ;; + h) usage && exit 0 ;; + u) DOTFILES_REMOTE="$OPTARG" ;; + *) + printf "Invalid option passed: %s\n" "$OPTARG" >&2 + ;; + esac + done + + shift $(( OPTIND - 1 )) + + # Stash any pending changes + git -C "$HOME" stash + + # Update the main repository + git -C "$HOME" fetch "$DOTFILES_REMOTE" "$DOTFILES_BRANCH" + git -C "$HOME" reset --hard "$DOTFILES_REMOTE/$DOTFILES_BRANCH" + + # Pull updates for all submodules + git -C "$HOME" submodule update --init --recursive --remote + + # Apply the stash + git -C "$HOME" stash apply +} + +usage() +{ + cat <<EOF +Usage: + ${0##*/} -h + ${0##*/} [-b <branch>] [-u <remote>] + +Utility application for dotfile maintenance. + +Options: + -b The name of the branch to use, defaults to "master" + -h Show this help text and exit. + -u The name of the remote to use, defaults to "origin" +EOF +} + +main "$@" diff --git a/.local/bin/vol b/.local/bin/vol index 4da6c18..84c913e 100755 --- a/.local/bin/vol +++ b/.local/bin/vol @@ -27,26 +27,31 @@ main() [ $# -lt 1 ] && usage && exit 1 + DEFAULT_SINK_NAME="$(pactl info | awk -F': ' '/Default Sink/ { print $NF }')" + DEFAULT_SINK_INDEX="$(pactl list short sinks | awk -v index_number="$DEFAULT_SINK_NAME" '$2==index_number {print $1}')" + case "$1" in inc) - amixer set Master ${2:-5}%+ > /dev/null - notify="Level increased to $(volume_level)%" + pactl set-sink-volume @DEFAULT_SINK@ +${2:-5}% > /dev/null + notify="Increased '$DEFAULT_SINK_NAME' ($DEFAULT_SINK_INDEX) to $(volume_level)%" ;; dec) - amixer set Master ${2:-5}%- > /dev/null - notify="Level decreased to $(volume_level)%" + pactl set-sink-volume @DEFAULT_SINK@ -${2:-5}% > /dev/null + notify="Decreased '$DEFAULT_SINK_NAME' ($DEFAULT_SINK_INDEX) to $(volume_level)%" ;; set) - amixer set Master $2% > /dev/null - notify="Level set to $(volume_level)%" + [ -z "$2" ] && usage && exit 1 + + pactl set-sink-volume @DEFAULT_SINK@ $2% > /dev/null + notify="Set '$DEFAULT_SINK_NAME' ($DEFAULT_SINK_INDEX) to $(volume_level)%" ;; on) - amixer set Master on > /dev/null - notify="Unmuted at $(volume_level)%" + pactl set-sink-mute @DEFAULT_SINK@ 0 > /dev/null + notify="Unmuted '$DEFAULT_SINK_NAME' ($DEFAULT_SINK_INDEX) at $(volume_level)%" ;; off) - amixer set Master off > /dev/null - notify="Muted" + pactl set-sink-mute @DEFAULT_SINK@ 1 > /dev/null + notify="Muted '$DEFAULT_SINK_NAME' ($DEFAULT_SINK_INDEX)" ;; toggle) case "$(volume_state)" in @@ -56,17 +61,23 @@ main() ;; esac + printf "%s\n" "$notify" notify-send -n 19269 -s -t 2 -i "$(volume_icon)" "Volume" "$notify" } volume_level() { - amixer get Master | awk '/Left:/ { print $5 }' | head -n 1 | tr -d '[]%' + + pactl list sinks \ + | perl -000ne 'if(/#'"$DEFAULT_SINK_INDEX"'/){/(Volume:.*)/; print "$1\n"}' \ + | sed 's/.*\ \(.*\)%.*/\1/g' } volume_state() { - amixer get Master | awk '/Left:/ { print $6 }' | head -n 1 | tr -d '[]' + pactl list sinks \ + | perl -000ne 'if(/#'"$DEFAULT_SINK_INDEX"'/){/(Mute:.*)/; print "$1\n"}' \ + | awk '$NF == "no" { print "on" } $NF == "yes" { print "off" }' } volume_icon() diff --git a/.local/bin/wscrot b/.local/bin/wscrot index 2970713..979dbef 100755 --- a/.local/bin/wscrot +++ b/.local/bin/wscrot @@ -3,4 +3,4 @@ p="~/pictures/scrot" cmd="mv \$f ${p} && notify-send \"Screenshot\" \"Saved to ${p}/\$f\"" -scrot -bsz window-%Y%m%d%H%M%S.png -e "${cmd}" +scrot -bs window-%Y%m%d%H%M%S.png -e "${cmd}" diff --git a/.local/bin/x b/.local/bin/x index ed5e26f..a47b1bc 100755 --- a/.local/bin/x +++ b/.local/bin/x @@ -12,12 +12,10 @@ then exit 1 fi - # Remove the old config - rm -f -- "$HOME/.xinitrc" - - # Add the base configuration - cat -- "$HOME/.local/etc/x/xinitrc" "$HOME/.local/etc/x/xinit.d/$1.rc" \ - >> "$HOME/.xinitrc" + cat \ + "$HOME/.local/etc/x/xinitrc" \ + "$HOME/.local/etc/x/xinit.d/$1.rc" \ + > "$HOME/.xinitrc" fi # Make sure the xinitrc exists, just in case @@ -28,4 +26,6 @@ then fi # start the X session -exec startx +startx +systemctl --user stop desktop-x11.target +systemctl --user stop desktop.target diff --git a/.local/bin/xdg-open b/.local/bin/xdg-open deleted file mode 120000 index ce4a72b..0000000 --- a/.local/bin/xdg-open +++ /dev/null @@ -1 +0,0 @@ -open
\ No newline at end of file |