diff --git a/bin/alert.sh b/bin/alert.sh new file mode 100755 index 00000000..6c8b302e --- /dev/null +++ b/bin/alert.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +mpg123 ~/music/'Tokyo+Mew+Mew+opening+(Full+Version)-XhifCN4HEQY.m4a' diff --git a/bin/bin2gtp b/bin/bin2gtp new file mode 100755 index 00000000..6d29d151 Binary files /dev/null and b/bin/bin2gtp differ diff --git a/bin/browser-select b/bin/browser-select new file mode 100755 index 00000000..5b57da6c --- /dev/null +++ b/bin/browser-select @@ -0,0 +1,11 @@ +#!/bin/sh + +case "$(printf "librewolf\\nnyxt\\nqutebrowser\\nlynx\\nfirefox" | bemenu -l 5 -i -p "Изабери прегледач: " )" in + + "librewolf") env librewolf ;; + "nyxt") nyxt ;; + "qutebrowser") qutebrowser ;; + "lynx") foot --app-id=lynx lynx ;; + "firefox") firefox ;; + +esac diff --git a/bin/chardetect b/bin/chardetect new file mode 100755 index 00000000..09f9ed19 --- /dev/null +++ b/bin/chardetect @@ -0,0 +1,8 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from chardet.cli.chardetect import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/bin/check-mail b/bin/check-mail new file mode 100755 index 00000000..ea1014ad --- /dev/null +++ b/bin/check-mail @@ -0,0 +1,3 @@ +#!/bin/sh + +mbsync -a && notify-send "MAIL CHECKED" diff --git a/bin/f2py b/bin/f2py new file mode 100755 index 00000000..40ce6f86 --- /dev/null +++ b/bin/f2py @@ -0,0 +1,8 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from numpy.f2py.f2py2e import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/bin/f2py3 b/bin/f2py3 new file mode 100755 index 00000000..40ce6f86 --- /dev/null +++ b/bin/f2py3 @@ -0,0 +1,8 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from numpy.f2py.f2py2e import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/bin/f2py3.9 b/bin/f2py3.9 new file mode 100755 index 00000000..40ce6f86 --- /dev/null +++ b/bin/f2py3.9 @@ -0,0 +1,8 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from numpy.f2py.f2py2e import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/bin/get_certs.sh b/bin/get_certs.sh new file mode 100755 index 00000000..7ba8d375 --- /dev/null +++ b/bin/get_certs.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +get_cert() { + SERVER=${1:-my.server.com} + PORT=${2:-993} + CERT_FOLDER=${3:-~/.cert} + + openssl s_client -connect ${SERVER}:${PORT} -showcerts 2>&1 < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'| sed -ne '1,/-END CERTIFICATE-/p' > ${CERT_FOLDER}/${SERVER}.pem +} + +get_cert mail.cock.li diff --git a/bin/google-oauthlib-tool b/bin/google-oauthlib-tool new file mode 100755 index 00000000..d84b1365 --- /dev/null +++ b/bin/google-oauthlib-tool @@ -0,0 +1,8 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from google_auth_oauthlib.tool.__main__ import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/bin/inactive-win-transparency.py b/bin/inactive-win-transparency.py new file mode 100755 index 00000000..af26c017 --- /dev/null +++ b/bin/inactive-win-transparency.py @@ -0,0 +1,28 @@ +#!/usr/bin/python + +# This script requires i3ipc-python package (install it from a system package manager +# or pip). +# It makes inactive windows transparent. Use `transparency_val` variable to control +# transparency strength in range of 0…1. + +import i3ipc + +transparency_val = '0.8'; +ipc = i3ipc.Connection() +prev_focused = None + +for window in ipc.get_tree(): + if window.focused: + prev_focused = window + else: + window.command('opacity ' + transparency_val) + +def on_window_focus(ipc, focused): + global prev_focused + if focused.container.id != prev_focused.id: # https://github.com/swaywm/sway/issues/2859 + focused.container.command('opacity 1') + prev_focused.command('opacity ' + transparency_val) + prev_focused = focused.container + +ipc.on("window::focus", on_window_focus) +ipc.main() diff --git a/bin/kaomoji b/bin/kaomoji new file mode 100755 index 00000000..44dedbba --- /dev/null +++ b/bin/kaomoji @@ -0,0 +1,15 @@ +#!/bin/sh + +dbfile=$HOME/.local/share/kaomoji/table + +category=$(grep -v "^$" "$dbfile" | sed 's/: .*//' | uniq | bemenu -l 41 -i -p "Choose category: ") + +if [ "$category" = "Other special" ]; then + output=$(grep "^$category: " "$dbfile" | sed "s/^$category: //" | bemenu -l 30 -i -p "Choose kaomoji: " | sed 's/^.*: //') +else + output=$(grep "^$category: " "$dbfile" | sed "s/^$category: //" | bemenu -l 30 -i -p "Choose kaomoji: ") +fi + +wl-copy "$output" + +pgrep -x mako >/dev/null && notify-send "$output copied to clipboard" diff --git a/bin/keymap-show b/bin/keymap-show new file mode 100755 index 00000000..7f957565 --- /dev/null +++ b/bin/keymap-show @@ -0,0 +1,10 @@ +#!/bin/sh + +original=$(hyprctl devices -j | jq '.keyboards[4].active_keymap') + +case "$original" in + '"English (US)"') echo "us" ;; + '"Serbian (Latin, QWERTY)"') echo "rs(lat)" ;; + '"Serbian (Cyrillic, ZE and ZHE swapped)"') echo "rs(cyr)" ;; + '"German (QWERTY)"') echo "de" ;; +esac diff --git a/bin/msmtp-queue b/bin/msmtp-queue new file mode 100755 index 00000000..eb76cc9f --- /dev/null +++ b/bin/msmtp-queue @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +##-------------------------------------------------------------- +## +## msmtp-queue : wrapper script for msmtpq +## to expose the management functions +## for the msmtp queue +## Copyright (C) 2011 Chris Gianniotis +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or, at +## your option, any later version. +## +##-------------------------------------------------------------- + +## msmtp-queue +## is only a wrapper +## it invokes the queue management functions of msmtpq +## by calling it as msmtpq --q-mgmt +## +## all configuration and documentation is in the msmtpq script + +## note that for 'special circumstances' +## e.g. embedded systems, etc. +## where the msmtpq script itself is not on the path +## change the below line to be +## exec /path/to/msmtpq --q-mgmt + +exec msmtpq --q-mgmt "$1" diff --git a/bin/msmtpq b/bin/msmtpq new file mode 100755 index 00000000..a5e70ba0 --- /dev/null +++ b/bin/msmtpq @@ -0,0 +1,486 @@ +#!/usr/bin/env bash + +##-------------------------------------------------------------- +## +## msmtpq : queue funtions to both use & manage the msmtp queue, +## as it was defined by Martin Lambers +## Copyright (C) 2008, 2009, 2010, 2011 Chris Gianniotis +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or, at +## your option, any later version. +## +##-------------------------------------------------------------- + +## msmtpq is meant to be used by an email client - in 'sendmail' mode +## for this purpose, it is invoked directly as 'msmtpq' +## it is also meant to be used to maintain the msmtp queue +## evoked by the wrapper script 'msmtp-queue' +## (which calls this script as msmtpq --q-mgmt) + +## there is a queue log file, distinct from the msmtp log, +## for all events & operations on the msmtp queue +## that is defined below + +## (mutt users, using msmtpq in 'sendmail' mode, +## should make at least the following two settings in their .muttrc +## set sendmail = /path/to/msmtpq +## set sendmail_wait = -1 +## +## please see the msmtp man page and docs for further mutt settings +## and optimisations +## ) + +## msmtpq now uses the following environment variables : +## EMAIL_CONN_NOTEST if set will suppress any testing for a connection +## EMAIL_CONN_TEST if unset or =p will use a ping test (debian.org) for a connection +## if =P will use a fast ping test (8.8.8.8) for a connection +## if =n will use netcat (nc) to test for a connection +## if =s will use bash sockets to test for a connection +## EMAIL_QUEUE_QUIET if set will cause suppression of messages and 'chatter' + +## two essential patches by Philipp Hartwig +## 19 Oct 2011 & 27 Oct 2011 + +##-------------------------------------------------------------- +## the msmtp queue contains unique filenames of the following form : +## two files for each mail in the queue +## +## creates new unique filenames of the form : +## MLF: ccyy-mm-dd-hh.mm.ss[-x].mail -- mail file +## MSF: ccyy-mm-dd-hh.mm.ss[-x].msmtp -- msmtp command line file +## where x is a consecutive number only appended for uniqueness +## if more than one mail per second is sent +##-------------------------------------------------------------- + + +dsp() { local L ; for L ; do [ -n "$L" ] && echo " $L" || echo ; done ; } +err() { dsp '' "$@" '' ; exit 1 ; } + + +## ====================================================================================== +## !!! please define or confirm the following three vars !!! +## !!! before using the msmtpq or msmtp-queue scripts !!! +## ====================================================================================== +## +## only if necessary (in unusual circumstances - e.g. embedded systems), +## enter the location of the msmtp executable (no quotes !!) +## e.g. ( MSMTP=/path/to/msmtp ) +MSMTP=msmtp +#[ -x "$MSMTP" ] || \ +# log -e 1 "msmtpq : can't find the msmtp executable [ $MSMTP ]" # if not found - complain ; quit +## +## set the queue var to the location of the msmtp queue directory +## if the queue dir doesn't yet exist, better to create it (0700) +## before using this routine +## e.g. ( mkdir msmtp.queue ) +## ( chmod 0700 msmtp.queue ) +## +## the queue dir - modify this to reflect where you'd like it to be (no quotes !!) +Q=~/.msmtp.queue +[ -d "$Q" ] || \ + err '' "msmtpq : can't find msmtp queue directory [ $Q ]" '' # if not present - complain ; quit +## +## set the queue log file var to the location of the msmtp queue log file +## where it is or where you'd like it to be +## ( note that the LOG setting could be the same as the ) +## ( 'logfile' setting in .msmtprc - but there may be ) +## ( some advantage in keeping the two logs separate ) +## if you don't want the log at all unset (comment out) this var +## LOG=~/log/msmtp.queue.log --> #LOG=~/log/msmtp.queue.log +## (doing so would be inadvisable under most conditions, however) +## +## the queue log file - modify (or comment out) to taste (but no quotes !!) +LOG="~/.local/share/msmtpq/msmtp.queue.log" +## ====================================================================================== + +umask 077 # set secure permissions on created directories and files + +declare -i CNT # a count of mail(s) currently in the queue +declare -a Q_LST # queue list array ; used selecting a mail (to send or remove) + +## do ; test this ! +#for sig in INT TERM EXIT; do +# trap "rm -f \"\$TMPFILE\"; [[ $sig == EXIT ]] || kill -$sig $$" $sig +#done +trap on_exit INT TERM EXIT # run 'on_exit' on exit +on_exit() { + [ -n "$LKD" ] && lock_queue -u 2>/dev/null # unlock the queue on exit if the lock was set here +} + +# +## ----------------------------------- common functions +# + +## make an entry to the queue log file, possibly an error +## (log queue changes only ; not interactive chatter) +## usage : log [ -e errcode ] msg [ msg ... ] +## opts : -e an error ; log msg & terminate w/prejudice +## display msg to user, as well +log() { + local ARG RC PFX="$('date' +'%Y %d %b %H:%M:%S')" + # time stamp prefix - "2008 13 Mar 03:59:45 " + if [ "$1" = '-e' ] ; then # there's an error exit code + RC="$2" # take it + shift 2 # shift opt & its arg off + fi + + [ -z "$EMAIL_QUEUE_QUIET" ] && dsp "$@" # display msg to user, as well as logging it + + if [ -n "$LOG" ] ; then # log is defined and in use + for ARG ; do # each msg line out + [ -n "$ARG" ] && \ + echo "$PFX : $ARG" >> "$LOG" # line has content ; send it to log + done + fi + + if [ -n "$RC" ] ; then # an error ; leave w/error return + [ -n "$LKD" ] && lock_queue -u # unlock here (if locked) + [ -n "$LOG" ] && \ + echo " exit code = $RC" >> "$LOG" # logging ok ; send exit code to log + exit $RC # exit w/return code + fi +} + +## write/remove queue lockfile for a queue op +lock_queue() { # <-- '-u' to remove lockfile + local LOK="${Q}/.lock" # lock file name + local -i MAX=240 SEC=0 # max seconds to gain a lock ; seconds waiting + + if [ -z "$1" ] ; then # lock queue + ## Philipp Hartwig patch #2 + 'mkdir' "$LOK" 2>/dev/null && LKD='t' + while [ -z "$LKD" ] && (( SEC < MAX )) ; do # lock file present + sleep 1 # wait a second + (( ++SEC )) # accumulate seconds + 'mkdir' "$LOK" 2>/dev/null && LKD='t' # make lockdir ; lock queue ; set flag + done # try again while locked for MAX secs + [ -z "$LKD" ] && \ + err '' "cannot use queue $Q : waited $MAX seconds for"\ + " lockdir [ $LOK ] to vanish ; giving up"\ + 'if you are certain that no other instance of this script'\ + " is running, then 'rmdir' the lock dir manually" '' # lock file still there, give up + + elif [ "$1" = '-u' ] ; then # unlock queue + 'rmdir' "$LOK" # remove the lock + unset LKD # unset flag + fi +} + +## test whether system is connected +## returns t/f (0/1) +connect_test() { + if [ -z "$EMAIL_CONN_TEST" ] || \ + [ "$EMAIL_CONN_TEST" = 'p' ] ; then # use ping test (default) + # verify net connection - ping ip address of debian.org + # would ping -qnc2 -w4 be better ? + # would ping -qnc1 -w10 or -w20 be better ? + ping -qnc1 -w4 debian.org >/dev/null 2>&1 || return 1 + elif [ "$EMAIL_CONN_TEST" = 'P' ] ; then # use quicker ping test + # I personally think that including a DNS lookup + # is a better connection test but some + # have found the above test too slow + ping -qnc1 -w4 8.8.8.8 >/dev/null 2>&1 || return 1 + elif [ "$EMAIL_CONN_TEST" = 'n' ] ; then # use netcat (nc) test + # must, of course, have netcat (nc) installed + which nc >/dev/null 2>&1 || \ + log -e 1 "msmtpq : can't find netcat executable [ nc ]" # if not found - complain ; quit + 'nc' -vz www.debian.org 80 || return 1 + elif [ "$EMAIL_CONN_TEST" = 's' ] ; then # use sh sockets test + # note that this does not work on debian systems + # where bash opened sockets are suppressed for security reasons + # this should be ok for single user systems (including embedded systems) + # test whether this is supported on your system before using + exec 3<>/dev/udp/debian.org/80 || return 1 # open socket on site ; use dns + exec 3<&- ; exec 3>&- # close socket + fi + return 0 +} + +# +## ----------------------------------- functions for queue management +## ----------------------------------- queue maintenance mode - (msmtp-queue) +# + +## show queue maintenance functions +usage() { # <-- error msg + dsp ''\ + 'usage : msmtp-queue functions' ''\ + ' msmtp-queue < op >'\ + ' ops : -r run (flush) mail queue - all mail in queue'\ + ' -R send selected individual mail(s) in queue'\ + ' -d display (list) queue contents (<-- default)'\ + ' -p purge individual mail(s) from queue'\ + ' -a purge all mail in queue'\ + ' -h this helpful blurt' ''\ + ' ( one op only ; any others ignored )' '' + [ -z "$1" ] && exit 0 || { dsp "$@" '' ; exit 1 ; } +} + +## get user [y/n] acknowledgement +ok() { + local R YN='Y/n' # default to yes + + [ "$1" = '-n' ] && \ + { YN='y/N' ; shift ; } # default to no ; change prompt ; shift off spec + + dsp "$@" + while true ; do + echo -n " ok [${YN}] ..: " + read R + case $R in + y|Y) return 0 ;; + n|N) return 1 ;; + '') [ "$YN" = 'Y/n' ] && return 0 || return 1 ;; + *) echo 'yYnN only please' ;; + esac + done +} + +## send a queued mail out via msmtp +send_queued_mail() { # <-- mail id + local FQP="${Q}/${1}" # fully qualified path name + local -i RC=0 # for msmtp exit code + + if [ -f "${FQP}.msmtp" ] ; then # corresponding .msmtp file found + [ -z "$EMAIL_CONN_NOTEST" ] && { # connection test + connect_test || \ + log "mail [ $2 ] [ $1 ] from queue ; couldn't be sent - host not connected" + } + + if $MSMTP $(< "${FQP}.msmtp") < "${FQP}.mail" ; then # this mail goes out the door + log "mail [ $2 ] [ $1 ] from queue ; send was successful ; purged from queue" # good news to user + 'rm' -f ${FQP}.* # nuke both queue mail files + ALT='t' # set queue changed flag + else # send was unsuccessful + RC=$? # take msmtp exit code + log "mail [ $2 ] [ $1 ] from queue ; send failed ; msmtp rc = $RC" # bad news ... + fi + return $RC # func returns exit code + else # corresponding MSF file not found + log "preparing to send .mail file [ $1 ] [ ${FQP}.mail ] but"\ + " corresponding .msmtp file [ ${FQP}.msmtp ] was not found in queue"\ + ' skipping this mail ; this is worth looking into' # give user the bad news + fi # (but allow continuation) +} + +## run (flush) queue +run_queue() { # <- 'sm' mode # run queue + local M LST="$('ls' $Q/*.mail 2>/dev/null)" # list of mails in queue + local -i NDX=0 + + if [ -n "$LST" ] ; then # something in queue + for M in $LST ; do # process all mails + ((NDX++)) + send_queued_mail "$(basename $M .mail)" "$NDX" # send mail - pass {id} only + done + else # queue is empty + [ -z "$1" ] && \ + dsp '' 'mail queue is empty (nothing to send)' '' + fi # inform user (if not running in sendmail mode) +} + +## display queue contents +display_queue() { # <-- { 'purge' | 'send' } (op label) ; { 'rec' } (record array of mail ids) + local M ID LST="$('ls' ${Q}/*.mail 2>/dev/null)" # list of mail ids in queue + + CNT=0 + if [ -n "$LST" ] ; then # list has contents (any mails in queue) + for M in $LST ; do # cycle through each + ID="$(basename $M .mail)" # take mail id from filename + ((CNT++)) + dsp '' "mail num=[ $CNT ] id=[ $ID ]" # show mail id ## patch in + 'egrep' -s --colour -h '(^From:|^To:|^Subject:)' "$M" # show mail info + [ -n "$2" ] && Q_LST[$CNT]="$ID" # bang mail id into array (note 1-based array indexing) + done + echo + else # no mails ; no contents + [ -z "$1" ] && \ + dsp '' 'no mail in queue' '' || \ + dsp '' "mail queue is empty (nothing to $1)" '' # inform user + exit 0 + fi +} + +## delete all mail in queue, after confirmation +purge_queue() { + display_queue 'purge' # show queue contents + if ok -n 'remove (purge) all mail from the queue' ; then + lock_queue # lock here + 'rm' -f "$Q"/*.* + log 'msmtp queue purged (all mail)' + lock_queue -u # unlock here + else + dsp '' 'nothing done ; queue is untouched' '' + fi +} + +## select a single mail from queue ; delete it or send it +## select by mail index (position in queue) or mail id +select_mail() { # <-- < 'purge' | 'send' > + local OK ID # mail id + local -i I NDX # mail index (position in queue) + + while true ; do # purge an individual mail from queue + display_queue "$1" 'rec' # show queue contents ; make mail ids array + + ## allow selection also by mail index + if [ $CNT -eq 1 ] ; then # only one mail in queue ; take its id + NDX=1 + ID="${Q_LST[1]}" + else # more than one mail ; select its id + while true ; do # get mail id + OK='t' # optimistic to a fault + dsp "enter mail number or id to $1" # <-- num or file name (only, no suff) + echo -n ' ( alone to exit ) ..: ' + read ID + [ -n "$ID" ] || return # entry made - or say good bye + + if [ "${ID:4:1}" != '-' ] ; then # mail id *not* entered ; test index num + for (( I=0 ; I<${#ID} ; I++ )) ; do # test index number + if [[ "${ID:${I}:1}" < '0' || \ + "${ID:${I}:1}" > '9' ]] ; then + dsp '' "[ $ID ] is neither a valid mail id"\ + 'nor a valid mail number' '' + unset OK + fi + done + [ -z "$OK" ] && continue # format not ok (not all nums) + + NDX=$ID + if [ $NDX -lt 1 ] || [ $NDX -gt $CNT ] ; then # test number range (1 - $CNT) + dsp '' "[ $NDX ] is out of range as a mail number"\ + "validity is from 1 to $CNT" + continue # try again + fi + + ID="${Q_LST[$NDX]}" # format & range were ok ; use it + break # valid mail selection + else # mail id entered + for (( NDX=1 ; NDX<=${#Q_LST[*]} ; NDX++ )) ; do # find entered id in queue list + [ "$ID" = "${Q_LST[$NDX]}" ] && break + done + [ $NDX -le ${#Q_LST[*]} ] && \ + break || \ + dsp '' "mail [ $ID ] not found ; invalid id" # mail selection valid (found) or + fi # fell through (not found) complain + done # and ask again + fi + + if ok '' "$1 :"\ + " mail num=[ $NDX ]"\ + " id=[ $ID ]" '' ; then # confirm mail op + if [ "$1" = 'purge' ] ; then # purging + lock_queue # lock here + 'rm' -f "$Q"/"$ID".* # msmtp - nukes single mail (both files) in queue + log "mail [ $ID ] purged from queue" # log op + lock_queue -u # unlock here + ALT='t' # mark that a queue alteration has taken place + else # sending + lock_queue # lock here + send_queued_mail "$ID" "$NDX" # send out the mail + lock_queue -u # unlock here + fi + else # user opts out + dsp '' 'nothing done to this queued email' # soothe user + [ $CNT -eq 1 ] && break # single mail ; user opted out + fi + dsp '' "--------------------------------------------------" + done + + if [ -n "$ALT" ] ; then # queue was changed + dsp '' 'done' '' + else # queue is untouched + dsp '' 'nothing done ; queue is untouched' '' + fi +} + +# +## ----------------------------------- functions for directly sending mail +## ----------------------------------- 'sendmail' mode - (msmtpq) +# + +## ('sendmail' mode only) +## make base filename id for queue +make_id() { + local -i INC # increment counter for (possible) base fqp name collision + + ID="$(date +%Y-%m-%d-%H.%M.%S)" # make filename id for queue (global + FQP="${Q}/$ID" # make fully qualified pathname vars) + ## Philipp Hartwig patch #1 + if [ -f "${FQP}.mail" -o -f "${FQP}.msmtp" ] ; then # ensure fqp name is unique + INC=1 # initial increment + while [ -f "${FQP}-${INC}.mail" -o -f "${FQP}-${INC}.msmtp" ] ; do # fqp name w/incr exists + (( ++INC )) # bump increment + done + ID="${ID}-${INC}" # unique ; set id + FQP="${FQP}-${INC}" # unique ; set fqp name + fi +} + +## ('sendmail' mode only) +## enqueue a mail +enqueue_mail() { # <-- all mail args ; mail text via TMP + if echo "$@" > "${FQP}.msmtp" ; then # write msmtp command line to queue .msmtp file + log "enqueued mail as : [ $ID ] ( $* ) : successful" # (queue .mail file is already there) + else # write failed ; bomb + log -e "$?" "queueing - writing msmtp cmd line { $* }"\ + " to [ ${ID}.msmtp ] : failed" + fi +} + +## ('sendmail' mode only) +## send a mail (if possible, otherwise enqueue it) +## if send is successful, msmtp will also log it (if enabled in ~/.msmtprc) +send_mail() { # <-- all mail args ; mail text via TMP + [ -z "$EMAIL_CONN_NOTEST" ] && { # connection test + connect_test || { + log "mail for [ $* ] : couldn't be sent - host not connected" + enqueue_mail "$@" # enqueue the mail + } + } + + if $MSMTP "$@" < "${FQP}.mail" > /dev/null ; then # send mail using queue .mail fil + log "mail for [ $* ] : send was successful" # log it + 'rm' -f ${FQP}.* # remove all queue mail files .mail & .msmtp file + run_queue 'sm' # run/flush any other mails in queue + else # send failed - the mail stays in the queue + log "mail for [ $* ] : send was unsuccessful ; msmtp exit code was $?"\ + "enqueued mail as : [ $ID ] ( $* )" # (queue .mail file is already there) + fi +} + +# +## -- entry point +# + +if [ ! "$1" = '--q-mgmt' ] ; then # msmtpq - sendmail mode + lock_queue # lock here + make_id # make base queue filename id for this mail + # write mail body text to queue .mail file + cat > "${FQP}.mail" || \ + log -e "$?" "creating mail body file [ ${FQP}.mail ] : failed" # test for error + # write msmtp command line to queue .msmtp file + echo "$@" > "${FQP}.msmtp" || \ + log -e "$?" "creating msmtp cmd line file { $* }"\ + " to [ ${ID}.msmtp ] : failed" # test for error + send_mail "$@" # send the mail if possible, queue it if not + lock_queue -u # unlock here +else # msmtp-queue - queue management mode + shift # trim off first (--q-mgmt) arg + OP=${1:1} # trim off first char of OP arg + case "$OP" in # sort ops ; run according to spec + r) lock_queue + run_queue + lock_queue -u ;; # run (flush) the queue + R) select_mail send ;; # send individual mail(s) in queue + d|'') display_queue ;; # display (list) all mail in queue (default) + p) select_mail purge ;; # purge individual mail(s) from queue + a) purge_queue ;; # purge all mail in queue + h) usage ;; # show help + *) usage "[ -$OP ] is an unknown msmtp-queue option" ;; + esac +fi + +exit 0 diff --git a/bin/pomo b/bin/pomo new file mode 100755 index 00000000..824afdbd --- /dev/null +++ b/bin/pomo @@ -0,0 +1,122 @@ +#!/usr/bin/env wish + +package require sound + +snack::sound beep -file "~/.local/share/pomo/beep.wav" +snack::sound chime -file "~/.local/share/pomo/chime.wav" + +set appname "Tk timer" + +# set timeleft {25 0} +# state can be "paused" or "running" or "stopped" +set state "stopped" +# phase can be "work" or "break" +set phase "work" + +proc dec {} { + global timeleft + if {[lindex $timeleft 0] == 0 && [lindex $timeleft 1] == 0} { + return 0 + } elseif {[lindex $timeleft 1] == 0} { + set timeleft [lreplace $timeleft 1 1 59] + set timeleft [lreplace $timeleft 0 0 [expr [lindex $timeleft 0] - 1]] + } else { + set timeleft [lreplace $timeleft 1 1 [expr [lindex $timeleft 1] - 1]] + } + return 1 +} + +proc notify {} { + variable msg + global phase + global appname + if {$phase == "work"} { + set msg "Break time: Remember to stretch" + } else { + set msg "Are you ready to get back to work?" + } + chime play + exec notify-send $appname $msg +} + +proc setuptime {} { + global phase + global timeleft + if {$phase == "work"} { + set timeleft {25 0} + } else { + set timeleft {5 0} + } + .display configure -text [format "%02d:%02d" [lindex $timeleft 0] [lindex $timeleft 1]] +} + +font create bigText -family Helvetica -size 72 +font create buttonText -family Helvetica -size 30 + +# play/pause button +button .pp -background blue -font buttonText -text "Play" -command playpause +button .skip -font buttonText -text "Skip" -command skip +label .display -font bigText + +proc next-phase {} { + global phase + global state + notify + set state "stopped" + .pp configure -text "Play" + if {$phase == "work"} { + set phase "break" + } else { + set phase "work" + } + setuptime +} + +proc countdown {} { + global state + global result + global timeleft + if {$state == "running"} { + set result [dec] + if {!$result} { + next-phase + } else { + .display configure -text [format "%02d:%02d" [lindex $timeleft 0] [lindex $timeleft 1]] + after 1000 countdown + } + } +} + +proc playpause {} { + global phase + global state + variable txt + if {$state == "running"} { + set state "paused" + set txt "Play" + } else { + if {$state == "stopped"} { + beep play + } + set state "running" + set txt "Pause" + countdown + } + .pp configure -text $txt +} + +proc skip {} { + after cancel countdown + next-phase +} + +grid rowconfigure . 0 -weight 1 +grid rowconfigure . 3 -weight 1 +grid columnconfigure . 0 -weight 1 +grid columnconfigure . 3 -weight 1 + +grid .display -column 1 -columnspan 2 -row 1 +grid .pp -column 1 -row 2 +grid .skip -column 2 -row 2 + +setuptime diff --git a/bin/pomodoro b/bin/pomodoro new file mode 100755 index 00000000..3c5c393a Binary files /dev/null and b/bin/pomodoro differ diff --git a/bin/powermenu.sh b/bin/powermenu.sh new file mode 100755 index 00000000..f05d025a --- /dev/null +++ b/bin/powermenu.sh @@ -0,0 +1,11 @@ +#!/bin/sh + + +case "$(printf " Poweroff \\n Restart \\n Suspend \\n Hibernate " | bemenu -l 4 -p "" -i)" in + + " Poweroff ") sudo -- poweroff ;; + " Restart ") sudo -- reboot ;; + " Suspend ") sudo -- loginctl suspend ;; + " Hibernate ") sudo -- loginctl hibernate ;; + +esac diff --git a/bin/record.sh b/bin/record.sh new file mode 100755 index 00000000..d78f7ef1 --- /dev/null +++ b/bin/record.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +while true; do + date=`date +"%Y-%m-%d"` + file_stub="/home/kappa/media/hacks-recordings/$date-rec-" + file_num="01" + while [ -e "$file_stub$file_num.mkv" ] ; do + file_num=`printf "%02d" $(($file_num + 1))` + done + + file_name="$file_stub$file_num.mkv" + + read -p "Start recording to file: $file_name? [y/N] " yn + + if [ "$yn" != "${yn#[Yy]}" ] ; then # IF answer DOES start with y or Y + wf-recorder -c h264_vaapi -d /dev/dri/renderD128 -f "$file_name" + fi +done diff --git a/bin/rubik b/bin/rubik new file mode 100755 index 00000000..03c8302a --- /dev/null +++ b/bin/rubik @@ -0,0 +1,3 @@ +#!/bin/sh + +java -jar ~/pkg/prisma/target/prisma-0.11.1-jar-with-dependencies.jar diff --git a/bin/screenshot b/bin/screenshot new file mode 100755 index 00000000..295103cb --- /dev/null +++ b/bin/screenshot @@ -0,0 +1,14 @@ +#!/bin/sh + +# This is bound to Shift+PrintScreen by default, requires maim. It lets you +# choose the kind of screenshot to take, including copying the image or even +# highlighting an area to copy. scrotcucks on suicidewatch right now. + +case "$(printf "a selected area\\ncurrent window\\nfull screen\\na selected area (copy)\\ncurrent window (copy)\\nfull screen (copy)" | bemenu -p "Screenshot which area?")" in + "a selected area") sleep 0.4 && import pic-selected-"$(date '+%y%m%d-%H%M-%S').png" ;; + "current window") sleep 0.4 && import -window "$(xdotool getactivewindow)" pic-window-"$(date '+%y%m%d-%H%M-%S').png" ;; + "full screen") sleep 0.4 && import -window root pic-full-"$(date '+%y%m%d-%H%M-%S').png" ;; + "a selected area (copy)") sleep 0.4 && import - | xclip -selection clipboard -t image/png ;; + "current window (copy)") sleep 0.4 && import -window "$(xdotool getactivewindow)" - | xclip -selection clipboard -t image/png ;; + "full screen (copy)") sleep 0.4 && import -window root - | xclip -selection clipboard -t image/png ;; +esac diff --git a/bin/scriptconv b/bin/scriptconv new file mode 100755 index 00000000..e27f45ab --- /dev/null +++ b/bin/scriptconv @@ -0,0 +1,43 @@ +#!/bin/sh + +if [ "$1" = "-l" ] +then + CONVMODE="lc" + shift +else + CONVMODE="cl" +fi + +lattocyr() +{ + # прво желимо да заменимо диграфе, да не бисмо заменили појединачне + # делове истих ако то није намера + + sed "s/Nj/Њ/g;\ + s/Lj/Љ/g;\ + s/Dž/Џ/g;\ + s/nj/њ/g;\ + s/lj/љ/g;\ + s/dž/џ/g;\ + y/abvgdđežzijklmnoprstćufhcčš/абвгдђежзијклмнопрстћуфхцчш/;\ + y/ABVGDĐEŽZIJKLMNOPRSTĆUFHCČŠ/АБВГДЂЕЖЗИЈКЛМНОПРСТЋУФХЦЧШ/" +} + +cyrtolat() +{ + sed "s/Њ/Nj/g;\ + s/Љ/Lj/g;\ + s/Џ/Dž/g;\ + s/њ/nj/g;\ + s/љ/lj/g;\ + s/џ/dž/g;\ + y/абвгдђежзијклмнопрстћуфхцчш/abvgdđežzijklmnoprstćufhcčš/;\ + y/АБВГДЂЕЖЗИЈКЛМНОПРСТЋУФХЦЧШ/ABVGDĐEŽZIJKLMNOPRSTĆUFHCČŠ/" +} + +if [ $CONVMODE = "cl" ] +then + cyrtolat +else + lattocyr +fi diff --git a/bin/slockf b/bin/slockf new file mode 100755 index 00000000..c22bc510 --- /dev/null +++ b/bin/slockf @@ -0,0 +1,3 @@ +#!/bin/sh + +slock -m "$(fortune | lolcat -ft)" diff --git a/bin/tordone b/bin/tordone new file mode 100755 index 00000000..f2366492 --- /dev/null +++ b/bin/tordone @@ -0,0 +1 @@ +notify-send "Transmission-daemon" "$TR_TORRENT_NAME has completely downloaded" diff --git a/bin/transadd b/bin/transadd new file mode 100755 index 00000000..efb7873e --- /dev/null +++ b/bin/transadd @@ -0,0 +1,9 @@ +#!/usr/bin/env sh + +# Mimeapp script for adding torrent to transmission-daemon, but will also start the daemon first if not running. + +# transmission-daemon sometimes fails to take remote requests in its first moments. + +pgrep -x transmission-da || (transmission-daemon && notify-send "Starting transmission daemon..." && sleep 3 && pkill -RTMIN+7 "${STATUSBAR:?}") + +transmission-remote -a "$@" && notify-send "Torrent added." diff --git a/bin/waybar-wttr.py b/bin/waybar-wttr.py new file mode 100755 index 00000000..44fc4c4e --- /dev/null +++ b/bin/waybar-wttr.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python + +import json +import requests +from datetime import datetime + +WEATHER_CODES = { + '113': '☀️', + '116': '⛅️', + '119': '☁️', + '122': '☁️', + '143': '🌫', + '176': '🌦', + '179': '🌧', + '182': '🌧', + '185': '🌧', + '200': '⛈', + '227': '🌨', + '230': '❄️', + '248': '🌫', + '260': '🌫', + '263': '🌦', + '266': '🌦', + '281': '🌧', + '284': '🌧', + '293': '🌦', + '296': '🌦', + '299': '🌧', + '302': '🌧', + '305': '🌧', + '308': '🌧', + '311': '🌧', + '314': '🌧', + '317': '🌧', + '320': '🌨', + '323': '🌨', + '326': '🌨', + '329': '❄️', + '332': '❄️', + '335': '❄️', + '338': '❄️', + '350': '🌧', + '353': '🌦', + '356': '🌧', + '359': '🌧', + '362': '🌧', + '365': '🌧', + '368': '🌨', + '371': '❄️', + '374': '🌧', + '377': '🌧', + '386': '⛈', + '389': '🌩', + '392': '⛈', + '395': '❄️' +} + +data = {} + + +weather = requests.get("https://wttr.in/zrenjanin?format=j1").json() + + +def format_time(time): + return time.replace("00", "").zfill(2) + + +def format_temp(temp): + return (hour['FeelsLikeC']+"°").ljust(3) + + +def format_chances(hour): + chances = { + "chanceoffog": "Fog", + "chanceoffrost": "Frost", + "chanceofovercast": "Overcast", + "chanceofrain": "Rain", + "chanceofsnow": "Snow", + "chanceofsunshine": "Sunshine", + "chanceofthunder": "Thunder", + "chanceofwindy": "Wind" + } + + conditions = [] + for event in chances.keys(): + if int(hour[event]) > 0: + conditions.append(chances[event]+" "+hour[event]+"%") + return ", ".join(conditions) + + +data['text'] = WEATHER_CODES[weather['current_condition'][0]['weatherCode']] + \ + " "+weather['current_condition'][0]['FeelsLikeC']+"°" + +data['tooltip'] = f"{weather['current_condition'][0]['weatherDesc'][0]['value']} {weather['current_condition'][0]['temp_C']}°\n" +data['tooltip'] += f"Feels like: {weather['current_condition'][0]['FeelsLikeC']}°\n" +data['tooltip'] += f"Wind: {weather['current_condition'][0]['windspeedKmph']}Km/h\n" +data['tooltip'] += f"Humidity: {weather['current_condition'][0]['humidity']}%\n" +for i, day in enumerate(weather['weather']): + data['tooltip'] += f"\n" + if i == 0: + data['tooltip'] += "Today, " + if i == 1: + data['tooltip'] += "Tomorrow, " + data['tooltip'] += f"{day['date']}\n" + data['tooltip'] += f"⬆️ {day['maxtempC']}° ⬇️ {day['mintempC']}° " + data['tooltip'] += f"🌅 {day['astronomy'][0]['sunrise']} 🌇 {day['astronomy'][0]['sunset']}\n" + for hour in day['hourly']: + if i == 0: + if int(format_time(hour['time'])) < datetime.now().hour-2: + continue + data['tooltip'] += f"{format_time(hour['time'])} {WEATHER_CODES[hour['weatherCode']]} {format_temp(hour['FeelsLikeC'])} {hour['weatherDesc'][0]['value']}, {format_chances(hour)}\n" + + +print(json.dumps(data)) diff --git a/bin/wayscreenshot b/bin/wayscreenshot new file mode 100755 index 00000000..b5a2d1c9 --- /dev/null +++ b/bin/wayscreenshot @@ -0,0 +1,16 @@ +#!/bin/sh + +# This is bound to Shift+PrintScreen by default, requires maim. It lets you +# choose the kind of screenshot to take, including copying the image or even +# highlighting an area to copy. scrotcucks on suicidewatch right now. + +case "$(printf "a selected area\\ncurrent window\\nfull screen\\na selected area (copy)\\ncurrent window (copy)\\nfull screen (copy)" | bemenu -p "Screenshot which area?")" in + "a selected area") sleep 0.4 && grim -g "$(slurp)" pic-selected-"$(date '+%y%m%d-%H%M-%S').png" ;; + # "current window") sleep 0.4 && grim -g "$(swaymsg -t get_tree | jq -r '.. | select(.focused?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"')" pic-window-"$(date '+%y%m%d-%H%M-%S').png" ;; + "current window") sleep 0.4 && grim -g "$(hyprctl activewindow | grep 'at:' | cut -d':' -f2 | tr -d ' ' | tail -n1) $(hyprctl activewindow | grep 'size:' | cut -d':' -f2 | tr -d ' ' | tail -n1 | sed s/,/x/g)" pic-window-"$(date '+%y%m%d-%H%M-%S').png" ;; + "full screen") sleep 0.4 && grim pic-full-"$(date '+%y%m%d-%H%M-%S').png" ;; + "a selected area (copy)") sleep 0.4 && grim -g "$(slurp)" - | wl-copy ;; + # "current window (copy)") sleep 0.4 && grim -g "$(swaymsg -t get_tree | jq -r '.. | select(.focused?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"')" - | wl-copy ;; + "current window (copy)") sleep 0.4 && grim -g "$(hyprctl activewindow | grep 'at:' | cut -d':' -f2 | tr -d ' ' | tail -n1) $(hyprctl activewindow | grep 'size:' | cut -d':' -f2 | tr -d ' ' | tail -n1 | sed s/,/x/g)" - | wl-copy ;; + "full screen (copy)") sleep 0.4 && grim - | wl-copy ;; +esac diff --git a/bin/wheel b/bin/wheel new file mode 100755 index 00000000..8149efbb --- /dev/null +++ b/bin/wheel @@ -0,0 +1,8 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from wheel.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/bin/ytdl-m3u8 b/bin/ytdl-m3u8 new file mode 100755 index 00000000..7812e478 --- /dev/null +++ b/bin/ytdl-m3u8 @@ -0,0 +1 @@ +youtube-dl --all-subs -f mp4 $@