From 1afd6902e774fd66f3882859af45a837ae83917e Mon Sep 17 00:00:00 2001 From: a Date: Mon, 12 Aug 2024 03:56:57 -0500 Subject: [PATCH] ok --- .../boilr/templates/fx/project.json | 5 + .../boilr/templates/fx/template/component.go | 36 ++ .../boilr/templates/river/project.json | 5 + .../boilr/templates/river/template/job.go | 57 +++ private_dot_local/script/executable_gamermode | 22 ++ private_dot_local/script/executable_gitsave | 13 + .../script/executable_goinstallbinaries | 31 ++ .../script/executable_inotify-consumers | 128 ++++++ .../script/executable_installappimage | 14 + .../script/executable_kubectl-ssh | 121 ++++++ private_dot_local/script/executable_mfly | 6 + .../script/executable_nodevpn_callback | 3 + private_dot_local/script/executable_openai | 367 ++++++++++++++++++ private_dot_local/script/executable_proton | 45 +++ .../script/executable_replace-subdir | 6 + .../script/executable_repotool-old | 56 +++ .../script/executable_scratchpad | 3 + private_dot_local/script/executable_shot | 5 + private_dot_local/script/executable_shrot | 2 + private_dot_local/script/executable_wttr | 69 ++++ private_dot_local/script/executable_yadmsync | 5 + 21 files changed, 999 insertions(+) create mode 100644 private_dot_config/boilr/templates/fx/project.json create mode 100644 private_dot_config/boilr/templates/fx/template/component.go create mode 100644 private_dot_config/boilr/templates/river/project.json create mode 100644 private_dot_config/boilr/templates/river/template/job.go create mode 100644 private_dot_local/script/executable_gamermode create mode 100644 private_dot_local/script/executable_gitsave create mode 100644 private_dot_local/script/executable_goinstallbinaries create mode 100644 private_dot_local/script/executable_inotify-consumers create mode 100644 private_dot_local/script/executable_installappimage create mode 100644 private_dot_local/script/executable_kubectl-ssh create mode 100644 private_dot_local/script/executable_mfly create mode 100644 private_dot_local/script/executable_nodevpn_callback create mode 100644 private_dot_local/script/executable_openai create mode 100644 private_dot_local/script/executable_proton create mode 100644 private_dot_local/script/executable_replace-subdir create mode 100644 private_dot_local/script/executable_repotool-old create mode 100644 private_dot_local/script/executable_scratchpad create mode 100644 private_dot_local/script/executable_shot create mode 100644 private_dot_local/script/executable_shrot create mode 100644 private_dot_local/script/executable_wttr create mode 100644 private_dot_local/script/executable_yadmsync diff --git a/private_dot_config/boilr/templates/fx/project.json b/private_dot_config/boilr/templates/fx/project.json new file mode 100644 index 0000000..20e44e8 --- /dev/null +++ b/private_dot_config/boilr/templates/fx/project.json @@ -0,0 +1,5 @@ +{ + "Name": "fx", + "Description": "create an fx component", + "Package":"" +} diff --git a/private_dot_config/boilr/templates/fx/template/component.go b/private_dot_config/boilr/templates/fx/template/component.go new file mode 100644 index 0000000..aba50f5 --- /dev/null +++ b/private_dot_config/boilr/templates/fx/template/component.go @@ -0,0 +1,36 @@ +{{- $pkg := env "PWD" | base | coalesce Package -}} +package {{$pkg}} + + +import ( + "context" + "log/slog" + + "go.uber.org/fx" +) + +type {{title $pkg}} struct { + log *slog.Logger +} + +type Params struct { + fx.In + + Ctx context.Context + Lc fx.Lifecycle + Log *slog.Logger +} + +type Result struct { + fx.Out + + Output *{{title $pkg}} +} + +func New(p Params) (r Result, err error) { + o := &{{title $pkg}}{} + o.log = p.Log + + r.Output = o + return +} diff --git a/private_dot_config/boilr/templates/river/project.json b/private_dot_config/boilr/templates/river/project.json new file mode 100644 index 0000000..d479970 --- /dev/null +++ b/private_dot_config/boilr/templates/river/project.json @@ -0,0 +1,5 @@ +{ + "Name": "river", + "Description": "create an river component", + "Package":"" +} diff --git a/private_dot_config/boilr/templates/river/template/job.go b/private_dot_config/boilr/templates/river/template/job.go new file mode 100644 index 0000000..baa1aaa --- /dev/null +++ b/private_dot_config/boilr/templates/river/template/job.go @@ -0,0 +1,57 @@ +{{- $pkg := env "PWD" | base | coalesce Package -}} +package {{$pkg}} + +import ( + "context" + "fmt" + "log/slog" + "path" + "reflect" + + "gfx.cafe/util/go/fxriver" + "github.com/riverqueue/river" + "go.uber.org/fx" +) + +var ( + packageName = path.Base(reflect.TypeOf(Args{}).PkgPath()) +) + +type Args struct { +} + +func (a *Args) Kind() string { + return packageName + ".task" +} + +type Worker struct { + river.WorkerDefaults[*Args] + + log *slog.Logger +} +type Params struct { + fx.In + + Ctx context.Context + Lc fx.Lifecycle + Log *slog.Logger +} + +type Result struct { + fx.Out + + Output fxriver.WorkConfigurer `group:"river_worker"` +} + +func New(p Params) (r Result, err error) { + o := &Worker{} + o.log = p.Log + + r.Output = fxriver.Wrap(o) + return +} + +func (o *Worker) Work(ctx context.Context, job *river.Job[*Args]) error { + o.log.Info("Starting Job", "name", packageName, "args", job.Args) + return fmt.Errorf("Job %s is not implemented", packageName) +} diff --git a/private_dot_local/script/executable_gamermode b/private_dot_local/script/executable_gamermode new file mode 100644 index 0000000..20cba01 --- /dev/null +++ b/private_dot_local/script/executable_gamermode @@ -0,0 +1,22 @@ +#!/bin/bash + + +gamermode_off(){ + notify-send -t 1600 'disabled gamermode' --icon=video-display + superctl start picom +# picom -b --log-file /var/log/picom.log --log-level INFO +} + +gamermode_on(){ + notify-send -t 1600 'enabled gamermode' --icon=video-display + superctl stop picom +# killall picom; +} + +if [ `pgrep -x picom` ]; then + gamermode_on +else + gamermode_off +fi +exit + diff --git a/private_dot_local/script/executable_gitsave b/private_dot_local/script/executable_gitsave new file mode 100644 index 0000000..7965496 --- /dev/null +++ b/private_dot_local/script/executable_gitsave @@ -0,0 +1,13 @@ +#!/bin/bash + + +git add -A +if [ "$#" -eq 0 ]; then + git commit -m "noot" +else + array=("$@") + str="${array[@]}" + git commit -m "$str" +fi +git push + diff --git a/private_dot_local/script/executable_goinstallbinaries b/private_dot_local/script/executable_goinstallbinaries new file mode 100644 index 0000000..0b76701 --- /dev/null +++ b/private_dot_local/script/executable_goinstallbinaries @@ -0,0 +1,31 @@ +#!/bin/sh + +go install github.com/klauspost/asmfmt/cmd/asmfmt@latest +go install github.com/go-delve/delve/cmd/dlv@latest +go install github.com/kisielk/errcheck@latest +go install github.com/davidrjenni/reftools/cmd/fillstruct@master +go install github.com/rogpeppe/godef@latest +go install golang.org/x/tools/cmd/goimports@master +go install github.com/mgechev/revive@latest +go install golang.org/x/tools/gopls@latest +go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest +go install honnef.co/go/tools/cmd/staticcheck@latest +go install github.com/fatih/gomodifytags@latest +go install golang.org/x/tools/cmd/gorename@master +go install github.com/jstemmer/gotags@master +go install golang.org/x/tools/cmd/guru@master +go install github.com/josharian/impl@main +go install honnef.co/go/tools/cmd/keyify@master +go install github.com/fatih/motion@latest +go install github.com/koron/iferr@master +go install golang.org/x/perf/cmd/benchstat@latest +go install github.com/wader/bump/cmd/bump@latest +go install mvdan.cc/gofumpt@latest +go install github.com/abice/go-enum@latest +go install golang.org/x/tools/cmd/gonew@latest +go install github.com/cweill/gotests@latest +go install golang.org/x/vuln/cmd/govulncheck@latest +go install github.com/abenz1267/gomvp@latest +go install github.com/tmc/json-to-struct@latest + +mise reshim diff --git a/private_dot_local/script/executable_inotify-consumers b/private_dot_local/script/executable_inotify-consumers new file mode 100644 index 0000000..11afb75 --- /dev/null +++ b/private_dot_local/script/executable_inotify-consumers @@ -0,0 +1,128 @@ +#!/bin/bash + +# Get the procs sorted by the number of inotify watches +# @author Carl-Erik Kopseng +# @latest https://github.com/fatso83/dotfiles/blob/master/utils/scripts/inotify-consumers +# Discussion leading up to answer: https://unix.stackexchange.com/questions/15509/whos-consuming-my-inotify-resources +# +# +########################################## Notice ########################################## +### Since Fall 2022 you should prefer using the following C++ version ### +### https://github.com/mikesart/inotify-info ### +############################################################################################ +# +# +# The fastest version of this script is here: https://github.com/fatso83/dotfiles/commit/inotify-consumers-v1-fastest +# Later PRs introduced significant slowdowns at the cost of better output, but it is insignificant on most machines +# See this for details: https://github.com/fatso83/dotfiles/pull/10#issuecomment-1122374716 + +main(){ + printf "\n%${WLEN}s %${WLEN}s\n" "INOTIFY" "INSTANCES" + printf "%${WLEN}s %${WLEN}s\n" "WATCHES" "PER " + printf "%${WLEN}s %${WLEN}s %s\n" " COUNT " "PROCESS " "PID USER COMMAND" + printf -- "------------------------------------------------------------\n" + generateData +} + +usage(){ + cat << EOF +Usage: $0 [--help|--limits] + -l, --limits Will print the current related limits and how to change them + -h, --help Show this help + +FYI: Check out Michael Sartain's C++ take on this script. The resulting native executable + is much faster, modern and feature rich. It can be found at + https://github.com/mikesart/inotify-info + + Requires building, but is well worth the few seconds :) +EOF +} + +limits(){ + printf "\nCurrent limits\n-------------\n" + sysctl fs.inotify.max_user_instances fs.inotify.max_user_watches + + cat <<- EOF +Changing settings permanently +----------------------------- +echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf +sudo sysctl -p # re-read config +EOF +} + +generateData() { + local -i PROC + local -i PID + local -i CNT + local -i INSTANCES + local -i TOT + local -i TOTINSTANCES + # read process list into cache + local PSLIST="$(ps ax -o pid,user=WIDE-COLUMN,command $COLSTRING)" + local INOTIFY="$(find /proc/[0-9]*/fdinfo -type f 2>/dev/null | xargs grep ^inotify 2>/dev/null)" + local INOTIFYCNT="$(echo "$INOTIFY" | cut -d "/" -s --output-delimiter=" " -f 3 |uniq -c | sed -e 's/:.*//')" + # unique instances per process is denoted by number of inotify FDs + local INOTIFYINSTANCES="$(echo "$INOTIFY" | cut -d "/" -s --output-delimiter=" " -f 3,5 | sed -e 's/:.*//'| uniq |awk '{print $1}' |uniq -c)" + local INOTIFYUSERINSTANCES="$(echo "$INOTIFY" | cut -d "/" -s --output-delimiter=" " -f 3,5 | sed -e 's/:.*//' | uniq | + while read PID FD; do echo $PID $FD $(grep -e "^ *${PID} " <<< "$PSLIST"|awk '{print $2}'); done | cut -d" " -f 3 | sort | uniq -c |sort -nr)" + set -e + + cat <<< "$INOTIFYCNT" | + { + while read -rs CNT PROC; do # count watches of processes found + echo "${PROC},${CNT},$(echo "$INOTIFYINSTANCES" | grep " ${PROC}$" |awk '{print $1}')" + done + } | + grep -v ",0," | # remove entires without watches + sort -n -t "," -k 2,3 -r | # sort to begin with highest numbers + { # group commands so that $TOT is visible in the printf + IFS="," + while read -rs PID CNT INSTANCES; do # show watches and corresponding process info + printf "%$(( WLEN - 2 ))d %$(( WLEN - 2 ))d %s\n" "$CNT" "$INSTANCES" "$(grep -e "^ *${PID} " <<< "$PSLIST")" + TOT=$(( TOT + CNT )) + TOTINSTANCES=$(( TOTINSTANCES + INSTANCES)) + done + # These stats should be per-user as well, since inotify limits are per-user.. + printf "\n%$(( WLEN - 2 ))d %s\n" "$TOT" "WATCHES TOTAL COUNT" +# the total across different users is somewhat meaningless, not printing for now. +# printf "\n%$(( WLEN - 2 ))d %s\n" "$TOTINSTANCES" "TOTAL INSTANCES COUNT" + } + echo "" + echo "INotify instances per user (e.g. limits specified by fs.inotify.max_user_instances): " + echo "" + ( + echo "INSTANCES USER" + echo "----------- ------------------" + echo "$INOTIFYUSERINSTANCES" + ) | column -t + echo "" + exit 0 +} + +# get terminal width +declare -i COLS=$(tput cols 2>/dev/null || echo 80) +declare -i WLEN=10 +declare COLSTRING="--columns $(( COLS - WLEN ))" # get terminal width + +if [ "$1" = "--limits" -o "$1" = "-l" ]; then + limits + exit 0 +fi + +if [ "$1" = "--help" -o "$1" = "-h" ]; then + usage + exit 0 +fi + +# added this line and moved some declarations to allow for the full display instead of a truncated version +if [ "$1" = "--full" -o "$1" = "-f" ]; then + unset COLSTRING + main +fi + +if [ -n "$1" ]; then + printf "\nUnknown parameter '$1'\n" >&2 + usage + exit 1 +fi +main diff --git a/private_dot_local/script/executable_installappimage b/private_dot_local/script/executable_installappimage new file mode 100644 index 0000000..b943dc1 --- /dev/null +++ b/private_dot_local/script/executable_installappimage @@ -0,0 +1,14 @@ +#!/bin/bash + +target="$HOME/.local/bin" + +echo "installing $2 to $1" + +if test -f $2; then + cp $2 "$target/$1" + chmod +x "$target/$1" +else + echo "file $2 doesnt exist" +fi + + diff --git a/private_dot_local/script/executable_kubectl-ssh b/private_dot_local/script/executable_kubectl-ssh new file mode 100644 index 0000000..7d43f3a --- /dev/null +++ b/private_dot_local/script/executable_kubectl-ssh @@ -0,0 +1,121 @@ +#!/usr/bin/env bash + +set -e + +ssh_node() { + node=$1 + if [ "$node" = "" ]; then + node=$(kubectl get node -o name | sed 's/node\///' | tr '\n' ' ') + node=${node::-1} + + if [[ "$node" =~ " " ]]; then + echo "Node name must be specified. Choose one of: [$node]" + exit 1 + else + echo "Single-node cluster detected. Defaulting to node $node" + fi + fi + + pod=$( + kubectl create -o name -f - </dev/null + kubectl attach -it $pod -c ssh-node + +} + +ssh_pod() { + # TODO: improve this + if [ "$1" == "" ]; then + echo "Pod name must be specified." + exit 1 + fi + kubectl exec -it "$@" bash || ( + echo "Running bash in pod failed; trying with sh" + kubectl exec -it "$@" sh + ) +} + +print_usage() { + echo "Provider-agnostic way of opening a remote shell to a Kubernetes node." + echo + echo "Enables you to access a node even when it doesn't run an SSH server or" + echo "when you don't have the required credentials. Also, the way you log in" + echo "is always the same, regardless of what provides the Kubernetes cluster" + echo "(e.g. Minikube, Kind, Docker Desktop, GKE, AKS, EKS, ...)" + echo + echo "You must have cluster-admin rights to use this plugin." + echo + echo "The primary focus of this plugin is to provide access to nodes, but it" + echo "also provides a quick way of running a shell inside a pod." + echo + echo "Examples: " + echo " # Open a shell to node of a single-node cluster (e.g. Docker Desktop)" + echo " kubectl ssh node" + echo + echo " # Open a shell to node of a multi-node cluster (e.g. GKE)" + echo " kubectl ssh node my-worker-node-1" + echo + echo " # Open a shell to a pod" + echo " kubectl ssh pod my-pod" + echo + echo "Usage:" + echo " kubectl ssh node [nodeName]" + echo " kubectl ssh pod [podName] [-n namespace] [-c container]" + exit 0 +} + +if [ "$1" == "--help" ]; then + print_usage +fi + +if [[ "$1" == node/* ]]; then + ssh_node ${1:5} +elif [ "$1" == "node" ]; then + ssh_node $2 +elif [[ "$1" == pod/* ]]; then + ssh_pod "$@" +elif [ "$1" == "pod" ]; then + shift + ssh_pod "$@" +else + print_usage +fi diff --git a/private_dot_local/script/executable_mfly b/private_dot_local/script/executable_mfly new file mode 100644 index 0000000..301acce --- /dev/null +++ b/private_dot_local/script/executable_mfly @@ -0,0 +1,6 @@ +#!/bin/sh + +first=$1 +shift + +fly -c "fly.${first}.toml" $@ diff --git a/private_dot_local/script/executable_nodevpn_callback b/private_dot_local/script/executable_nodevpn_callback new file mode 100644 index 0000000..3337094 --- /dev/null +++ b/private_dot_local/script/executable_nodevpn_callback @@ -0,0 +1,3 @@ +#!/bin/sh + +nordvpn login --callback "$1" diff --git a/private_dot_local/script/executable_openai b/private_dot_local/script/executable_openai new file mode 100644 index 0000000..53cc3eb --- /dev/null +++ b/private_dot_local/script/executable_openai @@ -0,0 +1,367 @@ +#!/usr/bin/env bash +# +# OpenAI CLI v2.2.2 +# Created by @janlay +# + +set -eo pipefail + +# openai-cli accepts various exported environment variables: +# OPENAI_API_KEY : OpenAI's API key +# OPENAI_API_ENDPOINT : Custom API endpoint +# OPENAI_MAX_TOKENS : Maximum number of tokens to use +# OPENAI_CHAT_MODEL : ChatGPT model +# OPENAI_DATA_DIR : Directory to store data +OPENAI_API_ENDPOINT="${OPENAI_API_ENDPOINT:-https://api.openai.com}" +OPENAI_API_KEY="${OPENAI_API_KEY:-sk-proj-Y9WpJ6RxNUgF0qqOrU8uT3BlbkFJgeRmt7zldRdiV1WrxC8G}" +OPENAI_MAX_TOKENS="${OPENAI_MAX_TOKENS:-2000}" +OPENAI_CHAT_MODEL="${OPENAI_CHAT_MODEL:-gpt-4-turbo}" +declare _config_dir="${OPENAI_DATA_DIR:-$XDG_CONFIG_HOME}" +OPENAI_DATA_DIR="${_config_dir:-$HOME/.openai}" + +# defaults +readonly _app_name=openai _app_version=2.2.2 +readonly default_api_version=1 default_api_name=chat/completions default_model="$OPENAI_CHAT_MODEL" default_topic=General + +declare -i chat_mode=0 dry_run=0 +declare tokens_file="$OPENAI_DATA_DIR/total_tokens" api_version=$default_api_version api_name=$default_api_name topic=$default_topic +declare dump_file dumped_file data_file temp_dir rest_args prompt_file prompt + +trap cleanup EXIT +cleanup() { + if [ -d "$temp_dir" ]; then + rm -rf -- "$temp_dir" + fi +} + +raise_error() { + [ "$2" = 0 ] || echo -n "$_app_name: " >&2 + echo -e "$1" >&2 + exit "${2:-1}" +} + +load_conversation() { + [ -f "$data_file" ] && cat "$data_file" || echo '{}' +} + +update_conversation() { + local entry="$2" data + [[ $entry == \{* ]] || entry=$(jq -n --arg content "$entry" '{$content}') + entry=$(jq --arg role "$1" '. += {$role}' <<<"$entry") + data=$(load_conversation) + jq --argjson item "$entry" '.messages += [$item]' <<<"$data" >"$data_file" +} + +save_tokens() { + local data num="$1" + [ -f "$data_file" ] && { + data=$(load_conversation) + jq --argjson tokens "$num" '.total_tokens += $tokens' <<<"$data" >"$data_file" + } + + data=0 + [ -f "$tokens_file" ] && data=$(cat "$tokens_file") + echo "$((data + num))" >"$tokens_file" +} + +read_prompt() { + # read prompt from args first + local word accepts_props=1 props='{}' real_prompt + if [ ${#rest_args[@]} -gt 0 ]; then + # read file $prompt_file word by word, and extract words starting with '+' + for word in "${rest_args[@]}"; do + if [ $accepts_props -eq 1 ] && [ "${word:0:1}" = '+' ]; then + word="${word:1}" + # determine value's type for jq + local options=(--arg key "${word%%=*}") value="${word#*=}" arg=--arg + [[ $value =~ ^[+-]?\ ?[0-9.]+$ || $value = true || $value = false || $value == [\[\{]* ]] && arg=--argjson + options+=("$arg" value "$value") + props=$(jq "${options[@]}" '.[$key] = $value' <<<"$props") + else + real_prompt="$real_prompt $word" + accepts_props=0 + fi + done + [ -n "$props" ] && echo "$props" >"$temp_dir/props" + fi + + if [ -n "$real_prompt" ]; then + [ -n "$prompt_file" ] && echo "* Prompt file \`$prompt_file' will be ignored as the prompt parameters are provided." >&2 + echo -n "${real_prompt:1}" >"$temp_dir/prompt" + elif [ -n "$prompt_file" ]; then + [ -f "$prompt_file" ] || raise_error "File not found: $prompt_file." 3 + [[ -s $prompt_file ]] || raise_error "Empty file: $prompt_file." 4 + fi +} + +openai_models() { + call_api | jq +} + +openai_moderations() { + local prop_file="$temp_dir/props" payload="{\"model\": \"text-moderation-latest\"}" + + # overwrite default properties with user's + read_prompt + [ -f "$prop_file" ] && payload=$(jq -n --argjson payload "$payload" '$payload | . += input' <"$prop_file") + + # append user's prompt to messages + local payload_file="$temp_dir/payload" input_file="$temp_dir/prompt" + [ -f "$input_file" ] || input_file="${prompt_file:-/dev/stdin}" + jq -Rs -cn --argjson payload "$payload" '$payload | .input = input' "$input_file" >"$payload_file" + + call_api | jq -c '.results[]' +} + +openai_images_generations() { + local prop_file="$temp_dir/props" payload="{\"n\": 1, \"size\": \"1024x1024\"}" + + # overwrite default properties with user's + read_prompt + [ -f "$prop_file" ] && payload=$(jq -n --argjson payload "$payload" '$payload | . += input | . += {response_format: "url"}' <"$prop_file") + + # append user's prompt to messages + local payload_file="$temp_dir/payload" input_file="$temp_dir/prompt" + [ -f "$input_file" ] || input_file="${prompt_file:-/dev/stdin}" + jq -Rs -cn --argjson payload "$payload" '$payload | .prompt = input' "$input_file" >"$payload_file" + + call_api | jq -r '.data[].url' +} + +openai_embeddings() { + local prop_file="$temp_dir/props" payload="{\"model\": \"text-embedding-ada-002\"}" + + # overwrite default properties with user's + read_prompt + [ -f "$prop_file" ] && payload=$(jq -n --argjson payload "$payload" '$payload | . += input' <"$prop_file") + + # append user's prompt to messages + local payload_file="$temp_dir/payload" input_file="$temp_dir/prompt" + [ -f "$input_file" ] || input_file="${prompt_file:-/dev/stdin}" + jq -Rs -cn --argjson payload "$payload" '$payload | .input = input' "$input_file" >"$payload_file" + + call_api | jq -c +} + +openai_chat_completions() { + [ -n "$dumped_file" ] || { + local prop_file="$temp_dir/props" payload="{\"model\": \"$default_model\", \"stream\": true, \"temperature\": 0.5, \"max_tokens\": $OPENAI_MAX_TOKENS}" + + # overwrite default properties with user's + read_prompt + [ -f "$prop_file" ] && { + payload=$(jq -n --argjson payload "$payload" '$payload | . += input | . += {messages: []}' <"$prop_file") + } + + local data + data=$(load_conversation | jq .messages) + [ "$topic" != "$default_topic" ] && { + if [ $chat_mode -eq 1 ]; then + # load all messages for chat mode + payload=$(jq --argjson messages "$data" 'setpath(["messages"]; $messages)' <<<"$payload") + else + # load only first message for non-chat mode + payload=$(jq --argjson messages "$data" 'setpath(["messages"]; [$messages[0]])' <<<"$payload") + fi + } + # append user's prompt to messages + local payload_file="$temp_dir/payload" input_file="$temp_dir/prompt" + [ -f "$input_file" ] || input_file="${prompt_file:-/dev/stdin}" + jq -Rs -cn --argjson payload "$payload" '$payload | .messages += [{role: "user", content: input}]' "$input_file" >"$payload_file" + } + + local chunk reason text role fn_name + call_api | while read -r chunk; do + [ -z "$chunk" ] && continue + chunk=$(cut -d: -f2- <<<"$chunk" | jq '.choices[0]') + reason=$(jq -r '.finish_reason // empty' <<<"$chunk") + [[ $reason = stop || $reason = function_call ]] && break + [ -n "$reason" ] && raise_error "API error: $reason" 10 + + # get role and function info from the first chunk + [ -z "$role" ] && { + role=$(jq -r '.delta.role // empty' <<<"$chunk") + fn_name=$(jq -r '.delta.function_call.name // empty' <<<"$chunk") + } + + # workaround: https://stackoverflow.com/a/15184414 + chunk=$( + jq -r '.delta | .function_call.arguments // .content // empty' <<<"$chunk" + printf x + ) + # ensure chunk is not empty + [ ${#chunk} -ge 2 ] || continue + + chunk="${chunk:0:${#chunk}-2}" + text="$text$chunk" + echo -n "$chunk" + done + + # append response to topic file for chat mode + [ "$chat_mode" -eq 1 ] && { + [ -n "$fn_name" ] && text=$(jq -n --arg name "$fn_name" --argjson arguments "${text:-\{\}}" '{function_call: {$name, $arguments}}') + + update_conversation user "$prompt" + update_conversation "$role" "$text" + } + echo +} + +# shellcheck disable=SC2120 +call_api() { + # return dumped file if specified + [ -n "$dumped_file" ] && { + cat "$dumped_file" + return + } + + local url="$OPENAI_API_ENDPOINT/v$api_version/$api_name" auth="Bearer $OPENAI_API_KEY" + + # dry-run mode + [ "$dry_run" -eq 1 ] && { + echo "Dry-run mode, no API calls made." + echo -e "\nRequest URL:\n--------------\n$url" + echo -en "\nAuthorization:\n--------------\n" + sed -E 's/(sk-.{3}).{41}/\1****/' <<<"$auth" + [ -n "$payload_file" ] && { + echo -e "\nPayload:\n--------------" + jq <"$payload_file" + } + exit 0 + } >&2 + + local args=("$url" --no-buffer -fsSL -H 'Content-Type: application/json' -H "Authorization: $auth") + [ -n "$payload_file" ] && args+=(-d @"$payload_file") + [ $# -gt 0 ] && args+=("$@") + + [ -n "$dump_file" ] && args+=(-o "$dump_file") + curl "${args[@]}" + [ -z "$dump_file" ] || exit 0 +} + +create_topic() { + update_conversation system "${rest_args[*]}" + raise_error "Topic '$topic' created with initial prompt '${rest_args[*]}'" 0 +} + +usage() { + raise_error "OpenAI Client v$_app_version + +SYNOPSIS + ABSTRACT + $_app_name [-n] [-a api_name] [-v api_version] [-o dump_file] [INPUT...] + $_app_name -i dumped_file + + DEFAULT_API (v$default_api_version/$default_api_name) + $_app_name [-c] [+property=value...] [@TOPIC] [-f file | prompt ...] + prompt + Prompt string for the request to OpenAI API. This can consist of multiple + arguments, which are considered to be separated by spaces. + -f file + A file to be read as prompt. If file is - or neither this parameter nor a prompt + is specified, read from standard input. + -c + Continues the topic, the default topic is '$default_topic'. + property=value + Overwrites default properties in payload. Prepend a plus sign '+' before property=value. + eg: +model=gpt-3.5-turbo-0301, +stream=false + + TOPICS + Topic starts with an at sign '@'. + To create new topic, use \`$_app_name @new_topic initial prompt' + + OTHER APIS + $_app_name -a models + +GLOBAL OPTIONS + Global options apply to all APIs. + -v version + API version, default is '$default_api_version'. + -a name + API name, default is '$default_api_name'. + -n + Dry-run mode, don't call API. + -o filename + Dumps API response to a file and exits. + -i filename + Uses specified dumped file instead of requesting API. + Any request-related arguments and user input are ignored. + + -- + Ignores rest of arguments, useful when unquoted prompt consists of '-'. + + -h + Shows this help" 0 +} + +parse() { + local opt + while getopts 'v:a:f:i:o:cnh' opt; do + case "$opt" in + c) + chat_mode=1 + ;; + v) + api_version="$OPTARG" + ;; + a) + api_name="$OPTARG" + ;; + f) + prompt_file="$OPTARG" + [ "$prompt_file" = - ] && prompt_file= + ;; + n) + dry_run=1 + ;; + i) + dumped_file="$OPTARG" + ;; + o) + dump_file="$OPTARG" + ;; + h | ?) + usage + ;; + esac + done + shift "$((OPTIND - 1))" + + # extract the leading topic + [[ "$1" =~ ^@ ]] && { + topic="${1#@}" + shift + } + + [ $chat_mode -eq 0 ] || { + [[ -n $topic && $topic != "$default_topic" ]] || raise_error 'Topic is required for chatting.' 2 + } + + rest_args=("$@") +} + +check_bin() { + command -v "$1" >/dev/null || raise_error "$1 not found. Use package manager (Homebrew, apt-get etc.) to install it." "${2:-1}" +} + +main() { + parse "$@" + check_bin jq 10 + + mkdir -p "$OPENAI_DATA_DIR" + data_file="$OPENAI_DATA_DIR/$topic.json" + temp_dir=$(mktemp -d) + + if [[ $topic == "$default_topic" || -f "$data_file" ]]; then + [ -z "$OPENAI_API_KEY" ] && raise_error 'OpenAI API key is required.' 11 + + local fn="openai_${api_name//\//_}" + [ "$(type -t "$fn")" = function ] || raise_error "API '$api_name' is not available." 12 + "$fn" + else + [ ${#rest_args[@]} -gt 0 ] || raise_error "Prompt for new topic is required" 13 + create_topic + fi +} + +main "$@" diff --git a/private_dot_local/script/executable_proton b/private_dot_local/script/executable_proton new file mode 100644 index 0000000..ef76c50 --- /dev/null +++ b/private_dot_local/script/executable_proton @@ -0,0 +1,45 @@ +#!/bin/sh + +# Usage: +# proton program.exe +# +# Example Env Vars: +# PROTONPREFIX="$HOME/proton_316" +# PROTONVERSION="Proton 3.16" + +# Folder name of the Proton version found under "steamapps/common/". +# proton_version="Proton - Experimental" +proton_version="Proton 7.0" + +# Path to installation directory of Steam. +# Alternate path: "$HOME/.steam/steam" +client_dir="$HOME/.steam/steam" + +# Default data folder for Proton/WINE environment. Folder must exist. +# If the environmental variable PROTONPREFIX is set, it will overwrite env_dir. +mkdir -p "$HOME/.proton/$proton_version" +env_dir="$HOME/.proton/$proton_version" +WINEPREFIX=protontricks + +# Proton modes to run +# run = start target app +# waitforexitandrun = wait for wineserver to shut down +# getcompatpath = linux -> windows path +# getnativepath = windows -> linux path +mode=run + +# ENVIRONMENTAL VARIABLES +if [ -n "${PROTONPREFIX+1}" ] +then + env_dir=$PROTONPREFIX +fi + +if [ -n "${PROTONVERSION+1}" ] +then + proton_version=$PROTONVERSION +fi + +# EXECUTE +export STEAM_COMPAT_CLIENT_INSTALL_PATH=$client_dir +export STEAM_COMPAT_DATA_PATH=$env_dir +"$client_dir/steamapps/common/$proton_version/proton" $mode $* diff --git a/private_dot_local/script/executable_replace-subdir b/private_dot_local/script/executable_replace-subdir new file mode 100644 index 0000000..08d92af --- /dev/null +++ b/private_dot_local/script/executable_replace-subdir @@ -0,0 +1,6 @@ +#!/bin/bash +# + +echo "use tool ruplacer instead" + +echo "eget your-tools/ruplacer" diff --git a/private_dot_local/script/executable_repotool-old b/private_dot_local/script/executable_repotool-old new file mode 100644 index 0000000..093751b --- /dev/null +++ b/private_dot_local/script/executable_repotool-old @@ -0,0 +1,56 @@ +#!/usr/bin/zsh + +ROOT_PREFIX="${REPO_ROOT_DIR:-$HOME/repo}" +GIT_USER="${REPO_GIT_USER:-git}" + +clean_path() +{ +stripped=$1 +prefix="http://" +stripped="${stripped#"$prefix"}" +prefix="https://" +stripped="${stripped#"$prefix"}" +prefix="git@" +stripped="${stripped#"$prefix"}" +suffix=".git" +stripped="${stripped%"$suffix"}" +stripped=$(echo "$stripped" | sed -e "s/:/\//1") +echo $stripped +} + +show_help() +{ + printf "Usage: repo \n" +} + +do_get() +{ + cleaned=$(clean_path $1) + output_path="$ROOT_PREFIX/$cleaned" + mkdir -p $output_path + if [ ! -d $output_path/.git ]; then + repourl=$(echo "$GIT_USER@$cleaned" | sed -e "s/\//:/1") + git clone $repourl $output_path + fi + cd $output_path +} + +do_goto() +{ +cleaned=$(clean_path $1) +output_path="$ROOT_PREFIX/$cleaned" +cd $output_path +} + + +case "$1" in + 'get' ) + do_get $2 + do_goto $2 + ;; + 'go' | "goto") + do_goto $2 + ;; + 'help' | "-h"| "-help" | "--help") + show_help +esac diff --git a/private_dot_local/script/executable_scratchpad b/private_dot_local/script/executable_scratchpad new file mode 100644 index 0000000..ef243e1 --- /dev/null +++ b/private_dot_local/script/executable_scratchpad @@ -0,0 +1,3 @@ +#!/bin/sh + +bspad hide diff --git a/private_dot_local/script/executable_shot b/private_dot_local/script/executable_shot new file mode 100644 index 0000000..d395a5e --- /dev/null +++ b/private_dot_local/script/executable_shot @@ -0,0 +1,5 @@ +#!/bin/sh + +OUTPUT_FILENAME="/home/a/shots/$(date '+%Y-%m-%d_%H:%M:%S').png" +scrot --freeze -F $OUTPUT_FILENAME -s +curl https://put.gay -H "authorization: $PASTE_TOKEN" --silent -F "file=@$OUTPUT_FILENAME;headers=\"bucket: shot\"" | xclip -selection clipboard diff --git a/private_dot_local/script/executable_shrot b/private_dot_local/script/executable_shrot new file mode 100644 index 0000000..56949a8 --- /dev/null +++ b/private_dot_local/script/executable_shrot @@ -0,0 +1,2 @@ +#!/bin/sh +scrot --freeze '/home/a/shots/%F_%T_$wx$h.png' -s -e 'xclip -selection clipboard -t image/png -i $f' diff --git a/private_dot_local/script/executable_wttr b/private_dot_local/script/executable_wttr new file mode 100644 index 0000000..b0a142d --- /dev/null +++ b/private_dot_local/script/executable_wttr @@ -0,0 +1,69 @@ +#!/usr/local/bin/gentee + +const : URL = "https://wttr.in/" +const : URLV2 = "https://v2.wttr.in/" +const : URLV3 = "https://v3.wttr.in/" +const : MOONURL = "https://wttr.in/moon@" + +func dirs() arr.str { + arr.str res = { + GetEnv("HOME")+"/.config/wttr/default-city.txt", + GetEnv("HOME")+"/.wttr", + } + return res +} + +func help() str { + return Format(` +Usage: wttr + -v2 + Use v2 (%s) + -v3 + Use v3 (%s) + -m + display moon (%s) + -c + Use metric units + -f + Use imperial units + -t -today + Display today's weather + `, + URLV2, + URLV3, + MOONURL, +) +} + +func request(str url) str { + map empty + map headers = {"User-Agent":"curl/7.87"} + return HTTPRequest(url, "GET", empty, headers) +} + +run { + if IsArg("h") || IsArg("help") { + Println(help()) + return + } + str loc = Arg("") + str url = URL + for fl in dirs() { + if ExistFile(fl): loc = TrimSpace(ReadFile(fl)); break; + } + if IsArg("v2"): url = URLV2 + if IsArg("v3"): url = URLV3 + if IsArg("m"): url = MOONURL + switch Arg("") + case "": + default: loc = Arg("") + switch loc + case "": url = url + "?" + default: url = url + loc +"?" + if IsArg("c"): url = url + "&m" + if IsArg("f"): url = url + "&u" + if (IsArg("t")||IsArg("today")): url = url + "&1n" + //Print(request(url)) + Run(`head`,"-n","-1", stdin: buf(request(url))) +} + diff --git a/private_dot_local/script/executable_yadmsync b/private_dot_local/script/executable_yadmsync new file mode 100644 index 0000000..805547b --- /dev/null +++ b/private_dot_local/script/executable_yadmsync @@ -0,0 +1,5 @@ +#!/bin/sh + +yadm add -u : +yadm commit -m "sync" +yadm push