adds more scripts

This commit is contained in:
Dominic Reich 2024-08-24 23:18:21 +02:00
parent 8405455ca5
commit a66f957e97
Signed by: dominic
GPG key ID: BC9D6AE1A3BE169A
29 changed files with 1304 additions and 0 deletions

58
aprs_sendstatus.py Executable file
View file

@ -0,0 +1,58 @@
#!/usr/bin/env python3.11
"""sending aprs status packets for my weather station"""
import aprslib
intervals = (
('weeks', 604800), # 60 * 60 * 24 * 7
('days', 86400), # 60 * 60 * 24
('hours', 3600), # 60 * 60
('minutes', 60),
('seconds', 1),
)
def get_uptime(granularity=2):
with open('/proc/uptime', 'r') as u:
uptime_seconds = int(float(u.readline().split()[0]))
return(display_time(uptime_seconds, granularity))
def display_time(seconds, granularity=2):
result = []
for name, count in intervals:
value = seconds // count
if value:
seconds -= value * count
if value == 1:
name = name.rstrip('s')
result.append("{} {}".format(value, name))
return ', '.join(result[:granularity])
def test():
"""test function"""
print('Uptime: ' + get_uptime())
def main():
"""main func"""
AIS = aprslib.IS("OE7DRT-13", passwd="*****", port=14580)
#AIS.sendall("OE7DRT-13>APRS,TCPIP*:>Running for " + get_uptime(2) + " on https://wx.oe7drt.com - happy new year!\r\n")
try:
AIS.connect()
except TimeoutError:
print("Could not send packets - Timeout.")
except:
print("An unexpected Error occured:")
AIS.sendall("OE7DRT-13>APRS,TCPIP*:>Weatherpage: https://wx.oe7drt.com\r\n")
if __name__ == "__main__":
main()

18
backup.sh Executable file
View file

@ -0,0 +1,18 @@
#!/bin/sh
# Simple rsync backup script for my MacBookPro
# Now using on the X1 Carbon running FreeBSD...
#
# Dominic Reich, OE7DRT, quick.hat4396@qtztsjosmprqmgtunjyf.com
doas rsync -avzhP --inplace --del --stats \
--exclude '.cache/***' \
--exclude '.gvfs/***' \
--exclude '.DS_Store' \
--exclude 'Thumbs.db' \
--exclude 'lost+found/***' \
--exclude '.Trash/***' \
--exclude '@eaDir/***' \
--exclude 'mnt/***' \
'/' \
home-server:/mnt/user/backup/x1-freebsd/

21
brot.sh Executable file
View file

@ -0,0 +1,21 @@
#!/bin/sh
# Brot bestellen, per email als Vorlage
# basic variables / text
day=$(date +%e)
#$(($DAY = $DAY + 1))
date="$(($day + 1))$(date +.%m.%y | sed 's/^\.0/\./')"
tmpfile="/tmp/brot-tmp-bestellung.txt"
subject="Bestellung fuer morgen $date"
msg="Hallo,\nich wuerde gerne folgendes
fuer morgen $date bestellen:\n\n 6x Broetlen
gestaubt\n 6x Semmeln\n 7x Apfelplunder\n 8x Salzstangen\n\nDanke!\n
\nAdresse\”zeile2 etc...\nzeile 3...."
# save the message to a tmp file
echo -e $msg > ${tmpfile}
# create the email and start mutt
neomutt -b "brot@archive.xxxxxxx.xyz" -s "$subject" -i ${tmpfile} -- "Gstreins Brot <info@xxxxxxx.xyz>"

127
call.py Executable file
View file

@ -0,0 +1,127 @@
#!/usr/bin/env python3.11
"""Lookup DMR users on radioid.net
This script fetches user information from radioid.net API and
prints them to stdout.
Created: maybe back in 2021
Last modified: 2023-01-02 00:07:34+0100
Usage:
------
With arguments
./call.py [callsign]|[dmrid]....
Without arguments - but enter them when the script asks you for them
./call.py
Examples:
---------
./call.py oe7drt oe%kbc
DMRID CALLSIGN FIRSTNAME CITY COUNTRY
2327180 OE7DRT Dominic Laengenfeld Austria
2327212 OE7DRT Dominic Laengenfeld Austria
2321001 OE1KBC Kurt Wien Austria
2321002 OE1KBC Kurt Wien Austria
2321003 OE1KBC Kurt Wien Austria
2328023 OE8KBC Kurt Saurachberg Austria
./call.py 2327212
DMRID CALLSIGN FIRSTNAME CITY COUNTRY
2327180 OE7DRT Dominic Laengenfeld Austria
2327212 OE7DRT Dominic Laengenfeld Austria
"""
import re # regex
import sys
import requests
def printFormatted(data: dict) -> None:
"""Formats and prints to stdout.
Expects data coming in as dict, returns nothing but
the text printed out to stdout."""
print("{:>7.8} {:<8.8} {:12.12} {:12.12} {:13.13}".format(
str(data['id']),
data['callsign'],
data['fname'],
data['city'],
data['country']))
def getFromCallsign(url: str, call: str) -> None:
"""Maps the given callsign to a DMRID
Uses the given base-url and callsign and fetches the
connected DMRIDs. Loops over the result and executes
printFormatted to print the results to stdout."""
r = requests.get(url + "/api/dmr/user/?callsign={}".format(call))
for ids in range(0, r.json()['count']):
printFormatted(r.json()['results'][ids])
def main():
"""main function
Runs if script is run by itself."""
if len(sys.argv) <= 1:
# Check if arguments were given, if not, let the user
# input some here
arguments = []
userinput = input("No arguments found, enter them now: ")
words = userinput.split()
for word in words:
arguments.append(word)
else:
# If arguments were given, take them and move on
arguments = sys.argv[1:]
# Using these regex pattern to match agains valid DMRIDs
# and callsigns. The callsign pattern was taken from
# <https://gist.github.com/JoshuaCarroll/f6b2c64992dfe23feed49a117f5d1a43>
# and slighty modifed to also allow the percent sign (%) used by
# used by radioid.net as wildmask.
dmrid_userid_patt = re.compile("^[0-9]{7}$")
dmrid_rep_patt = re.compile("^[0-9]{6}$")
# dmrid_other_patt = re.compile("^[0-9]{0,5}$")
call_patt = re.compile("^[a-zA-Z0-9%]{1,3}[0123456789%][a-zA-Z0-9%]{0,2}[a-zA-Z%]$")
baseurl = 'https://www.radioid.net'
print(" DMRID CALLSIGN FIRSTNAME CITY COUNTRY")
for arg in arguments:
if dmrid_userid_patt.match(arg):
# A valid DMRID was found, so we have to lookup the
# callsign and we may get more DMRIDs for this OM
# Valid means 7 chars long, all numbers. We do not know
# yet if the id really exists.
r = requests.get(baseurl + '/api/dmr/user/?id={}'.format(arg))
if r.status_code == 200:
# Only fetch more DMRIDs if the first one exists,
# otherwise we would try to run code on an non
# existing variable
getFromCallsign(baseurl, r.json()['results'][0]['callsign'])
elif dmrid_rep_patt.match(arg):
# A valid repeater ID was found. Valid means, technically
# correct -> 6 characters long, all numbers
print("{} looks like a repeater. Skipping for now.".format(arg))
# elif dmrid_other_patt.match(arg):
# # Print a warning for numbers less than 6 characters
# print("{} is not a valid dmr id!".format(arg))
elif call_patt.match(arg):
getFromCallsign(baseurl, arg)
else:
print('{} is an invalid value'.format(arg))
if __name__ == "__main__":
main()

36
change_subject.sh Executable file
View file

@ -0,0 +1,36 @@
#!/usr/bin/env bash
FILE="/tmp/mailtmp.txt"
OLD_SUBJECT="/tmp/mailsubject.txt"
trap "rm ${FILE}; exit" SIGHUP SIGINT SIGTERM
# create empty file
>${FILE}
if [[ -w ${OLD_SUBJECT} ]]; then
# read subject from file
oldsubject=$(<${OLD_SUBJECT})
else
# create empty file
>$OLD_SUBJECT
oldsubject="New subject"
fi
# set subject line
kdialog --inputbox "New subject:" "${oldsubject}" >${OLD_SUBJECT}
subject=$(<${OLD_SUBJECT})
# save mail in file
cat $* > ${FILE}
# change subject line
sed -i "s/^Subject: \(.*\)/Subject: ${subject}/" ${FILE}
# return file
cat ${FILE}
# delete email file
rm ${FILE}

37
date.php Executable file
View file

@ -0,0 +1,37 @@
#!/usr/bin/env php
<?php
/*
* PHP Skript zum Umrechnen von Datumsangaben (UNIX Timestamps)
* Author: Dominic Reich <quick.hat4396@qtztsjosmprqmgtunjyf.com>
* Last modified: Freitag, 02.11.2018 06:13
*
*/
/*
* THIS SCRIPT IS FOR COMMAND LINE (CLI) ONLY!!
* run with "php <script path & name>
* php date.php [options] [args]
*
*/
if ( isset ( $argv[1] ) ) {
if ( !preg_match ( "/^[0-9]{10}$/", $argv[1] ) ) {
die ( "Ungültiger Timestamp!\n" );
/*
* TODO: delete this part, this is now implemented in regex above
} elseif ( strlen ( trim ( $argv[1] ) ) != 10 ) {
die ( "Ungültiger Timestamp!\n" );
*/
};
echo " Timestamp: $argv[1]\n";
echo " Date: " . date ( "d.m.Y H:i:s", $argv[1] );
// echo "Actual Timestamp: " . time() . "\n";
// echo " Actual Date: " . date ( "d.m.Y H:i:s", time() );
} else {
// Default: printing timestamp and calculate it to std date format (human readable)
echo "Actual Timestamp: " . time() . "\n";
echo " Actual Date: " . date ( "d.m.Y H:i:s", time() );
};
?>

21
file_email.sh Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Save piped email to "$1/YYMMDD SUBJECT.eml"
# Don't overwrite existing file
set -o noclobber
message=$(cat)
mail_date=$(<<<"$message" ggrep -oPm 1 '^Date: ?\K.*')
formatted_date=$(date -f "$mail_date" +%y%m%d)
# Get the first line of the subject, and change / to so it's not a subdirectory
subject=$(<<<"$message" ggrep -oPm 1 '^Subject: ?\K.*' | sed 's,/,,g')
if [[ $formatted_date == '' ]]; then
echo Error: no date parsed
exit 1
elif [[ $subject == '' ]]; then
echo Warning: no subject found
fi
echo "${message}" > "$1/$formatted_date $subject.eml" && echo Email saved to "$1/$formatted_date $subject.eml"

44
forum_sig.cron.sh Executable file
View file

@ -0,0 +1,44 @@
#!/bin/sh
# generate forum signatures for black and white backgrounds
# files get optimized with optipng, advpng and pngcrush
# you may want to install them; if you don't have them installed
# the output files get not optimized
# for random output I utilize a perl script `randomquote.pl` which
# is not my own and the author does not want it to be re-distributed
# so you might want to find something that suits your need
#
# Author: Dominic Reich <quick.hat4396@qtztsjosmprqmgtunjyf.com>
# Last modified: 2024-01-15 02:36
#
# files create in actual dir _dark.png and _light.png are added to filename
file_prefix=forumsig
quote=$(~/bin/randomquote.pl | fold -sw 76)
# dark
convert -background black -fill \#ddd -font /usr/local/share/fonts/spleen/spleen-32x64.otf \
-antialias -pointsize 20 label:"$quote" ${file_prefix}_dark.png
# light
convert -background white -fill \#222 -font /usr/local/share/fonts/spleen/spleen-32x64.otf \
-antialias -pointsize 20 label:"$quote" ${file_prefix}_light.png
missing=""
command -v optipng > /dev/null 2>&1 || { missing="$missing optiping"; }
command -v advpng > /dev/null 2>&1 || { missing="$missing advpng"; }
command -v pngcrush > /dev/null 2>&1 || { missing="$missing pngcrush"; }
if [ -n "$missing" ]
then
echo >&2 "could not find:$missing"
exit 1
fi
for file in ${file_prefix}_{dark,light}.png
do
optipng -nb -nc $file > /dev/null 2>&1
advpng -z4 $file > /dev/null 2>&1
pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time -ow $file > /dev/null 2>&1
done

48
hexroute.sh Executable file
View file

@ -0,0 +1,48 @@
#!/usr/bin/env bash
# source: https://mgergi.hu/en/it-blog/static-route-dhcp-pfsense
check_ip(){
local n=0 val=1
for i in ${1//./ }; do
[ $i -lt 0 -o $i -gt 255 ] && val=0
n=$[n+1]
done
[ $n -ne 4 ] && val=0
if [ $val -ne 1 ] ; then
echo "Invalid IP: $1" >&2
exit 1
fi
}
to_bin(){
local BIN=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1})
for i in ${1//./ }; do
echo -n ${BIN[$i]}
done
}
while [ $# -gt 0 ] ; do
nw=${1%/*}; nm=${1#*/}; gw=$2
check_ip $nw; check_ip $gw
if [ ${#nm} -gt 2 ] ; then
check_ip $nm
nmbin=$(to_bin $nm)
if echo $nmbin | grep -q "01" ; then
echo "Invalid netmask: $nm" >&2
exit 1
else
nmbin=${nmbin//0/}
fi
nm=${#nmbin}
echo $nm
fi
gwhex=$(printf "%02x:%02x:%02x:%02x" ${2//./ })
nwhex=$(printf "%02x:%02x:%02x:%02x" ${nw//./ })
nmhex=$(printf "%02x" ${nm//./ })
[ $nm -le 24 ] && nwhex=${nwhex%:*}
[ $nm -le 16 ] && nwhex=${nwhex%:*}
[ $nm -le 8 ] && nwhex=${nwhex%:*}
echo -n $nmhex:$nwhex:$gwhex
shift 2
[ $# -gt 0 ] && echo -n ":"
done
echo

64
lh.py Executable file
View file

@ -0,0 +1,64 @@
#!/usr/bin/env python3.11
"""open the lastheard page on brandmeister
"""
import re, argparse, webbrowser
def main():
"""main function"""
parser = argparse.ArgumentParser(description='Opens a last-heard table on Brandmeister in your browser')
subparser = parser.add_subparsers(dest='selection')
talkgroup = subparser.add_parser('tg')
callsign = subparser.add_parser('call')
dmrid = subparser.add_parser('id')
talkgroup.add_argument('TG', help='Talkgroup', type=int)
callsign.add_argument('CALLSIGN', help='Callsign', type=str)
dmrid.add_argument('DMRID', help='DMR-ID (Integer)', type=int)
args = parser.parse_args()
if args.selection == 'tg':
tg_pattern = re.compile("^([1-9]|[1-9][0-9]{1,6})$")
if tg_pattern.match(str(args.TG)):
url = 'https://brandmeister.network/?page=lh&DestinationID={}'.format(args.TG)
#print(url)
else:
print("not a valid tg number:", args.TG)
exit(1)
elif args.selection == 'call':
call_pattern = re.compile("^[a-zA-Z0-9]{1,3}[0123456789][a-zA-Z0-9]{0,2}[a-zA-Z]$")
if call_pattern.match(str(args.CALLSIGN)):
url = 'https://brandmeister.network/?page=lh&SourceCall={}'.format(args.CALLSIGN.upper())
#print(url)
else:
print("not a valid callsign:", args.CALLSIGN)
exit(1)
elif args.selection == 'id':
dmrid_userid_pattern = re.compile("^[0-9]{7}$")
dmrid_repeater_pattern = re.compile("^[0-9]{6}$")
if dmrid_userid_pattern.match(str(args.DMRID)):
url = 'https://brandmeister.network/?page=lh&SourceID={}'.format(args.DMRID)
#print(url)
elif dmrid_repeater_pattern.match(str(args.DMRID)):
url = 'https://brandmeister.network/?page=lh&ContextID={}'.format(args.DMRID)
#print(url)
else:
print("not a valid DMR-ID:", args.DMRID)
exit(1)
else:
parser.print_help()
exit(1)
webbrowser.open(url, new=0, autoraise=True)
#print(url)
if __name__ == "__main__":
main()

84
lh.sh Executable file
View file

@ -0,0 +1,84 @@
#!/usr/bin/env bash
# Get last heard time via ham-digital.org
# Author: Dominic Reich, OE7DRT, quick.hat4396@qtztsjosmprqmgtunjyf.com
#
# Good DX and vy 73 de OE7DRT
command -v w3m > /dev/null 2>&1 || { echo >&2 "w3m not found"; exit 1; }
print_usage () {
echo >&2 "usage: `basename $0` [dmr_id | callsign]"
exit 1
}
if [ $# -ne 1 ]
then
print_usage
fi
getLH () {
CALL=`echo $1 | tr a-z A-Z`
FILE=/tmp/$CALL
OUTFILE=/tmp/${CALL}_LH
w3m "https://ham-digital.org/dmr-lh.php?callsign=$CALL" > $FILE
c=`grep $CALL $FILE | wc -l | xargs`
while [ $c -gt 0 ]
do
#OUT=`grep $CALL $FILE | head -n $c | tail -n 1 | awk '{ print $2,$3,$5,$6,$4,$8,$9,$13,$10 }'`
#OUT=`grep $CALL $FILE | head -n $c | tail -n 1 | awk '{ print $6,"was last heard on",$2,$3,"via",$9 }'`
OUT=`grep $CALL $FILE | head -n $c | tail -n 1`
echo $OUT >> $OUTFILE
((c--))
done
if [ ! -s $OUTFILE ]
then
echo No records found for »${CALL}«
rm ${FILE}
exit 1
fi
sort $OUTFILE
rm $FILE $OUTFILE
}
getCALLSIGN () {
ID=$1
FILE=/tmp/$ID
w3m "https://ham-digital.org/dmr-userreg.php?usrid=$ID" > $FILE
CALL=`grep $ID $FILE | awk '{ print $4 }'`
rm $FILE
if [ -z $CALL ]
then
exit 1
fi
getLH $CALL
}
checkID () {
if [[ ! $1 =~ ^[0-9]{7}$ ]]
then
echo >&2 "no valid dmr_id supplied"
exit 1
fi
}
if [ "$1" -eq "$1" ] 2>/dev/null
then
ID="$1"
checkID $ID
else
CALL="$1"
fi
if [ ! -z $ID ]
then
getCALLSIGN $ID
exit 0
elif [ ! -z $CALL ]
then
getLH $CALL
exit 0
else
print_usage
fi

37
lock.sh Executable file
View file

@ -0,0 +1,37 @@
#!/bin/sh
BLANK='#00000000'
CLEAR='#ffffff22'
DEFAULT='#ff00ffcc'
TEXT='#ee00eeee'
WRONG='#880000bb'
VERIFYING='#bb00bbbb'
i3lock \
--insidever-color=$CLEAR \
--ringver-color=$VERIFYING \
\
--insidewrong-color=$CLEAR \
--ringwrong-color=$WRONG \
\
--inside-color=$BLANK \
--ring-color=$DEFAULT \
--line-color=$BLANK \
--separator-color=$DEFAULT \
\
--verif-color=$TEXT \
--wrong-color=$TEXT \
--time-color=$TEXT \
--date-color=$TEXT \
--layout-color=$TEXT \
--keyhl-color=$WRONG \
--bshl-color=$WRONG \
\
--screen 1 \
--blur 9 \
--clock \
--indicator \
--time-str="%H:%M:%S" \
--date-str="%A, %Y-%m-%d" \
--keylayout 1 \

3
mailtomutt.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
exec alacritty --title Newmail -e neomutt "$@"

13
powersave-arch.sh Executable file
View file

@ -0,0 +1,13 @@
#!/bin/sh
case $( cat /sys/class/power_supply/AC/online ) in
(0)
blight set $(cat ${HOME}/.backlight-bat)% 1> /dev/null 2> /dev/null
;;
(1)
blight set $(cat ${HOME}/.backlight-ac)% 1> /dev/null 2> /dev/null
;;
esac

32
powersave-freebsd.sh Executable file
View file

@ -0,0 +1,32 @@
#!/bin/sh
case $( sysctl -n hw.acpi.acline ) in
(0) # BATTERY
doas sysctl dev.hwpstate_intel.0.epp=0 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.1.epp=50 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.2.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.3.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.4.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.5.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.6.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.7.epp=100 1> /dev/null 2> /dev/null
#backlight 20 1> /dev/null 2> /dev/null
backlight $(cat ${HOME}/.backlight-bat) 1> /dev/null 2> /dev/null
;;
(1) # AC
doas sysctl dev.hwpstate_intel.0.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.1.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.2.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.3.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.4.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.5.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.6.epp=100 1> /dev/null 2> /dev/null
doas sysctl dev.hwpstate_intel.7.epp=100 1> /dev/null 2> /dev/null
#backlight 100 1> /dev/null 2> /dev/null
backlight $(cat ${HOME}/.backlight-ac) 1> /dev/null 2> /dev/null
;;
esac

14
powersave-openbsd.sh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/sh
case $( sysctl -n hw.power ) in
(0) # BATTERY
doas wsconsctl display.brightness=$(cat ${HOME}/.backlight-bat) 1> /dev/null 2> /dev/null
;;
(1) # AC
doas wsconsctl display.brightness=$(cat ${HOME}/.backlight-ac) 1> /dev/null 2> /dev/null
;;
esac

125
rpt.py Executable file
View file

@ -0,0 +1,125 @@
#!/usr/bin/env python3.11
"""Lookup DMR users on radioid.net
This script fetches repeater information from radioid.net API and
prints them to stdout.
Created: 2022-08-27 12:08:11+0200
Last modified: 2022-08-27 12:31:42+0200
Usage:
------
With arguments
./rpt.py [callsign]|[dmrid]....
Without arguments - but enter them when the script asks you for them
./rpt.py
Examples:
---------
no examples yet...
"""
import re # regex
import sys
import requests
def printFormatted(data: dict) -> None:
"""Formats and prints to stdout.
Expects data coming in as dict, returns nothing but
prints the text to stdout."""
""" id call city state country color freq offset trustee """
print("{:>7.8} {:<8.8} {:16.16} {:23.23} {:13.13} {:2.2} {:9.9} {:6.6} {:8.8}".format(
str(data['id'] or ''),
str(data['callsign'] or ''),
str(data['city'] or ''),
str(data['state'] or ''),
str(data['country'] or ''),
str(data['color_code'] or ''),
str(data['frequency'] or ''),
str(data['offset'] or ''),
str(data['trustee'] or '')))
def printHeaderLine():
"""Prints the first line of table """
print(" DMRID CALLSIGN CITY STATE COUNTRY CC FREQUENCY OFFSET TRUSTEE")
def getFromCallsign(url: str, call: str) -> None:
"""Maps the given callsign to a DMRID
Uses the given base-url and callsign and fetches the
connected DMRIDs. Loops over the result and executes
printFormatted to print the results to stdout."""
r = requests.get(url + "/api/dmr/repeater/?callsign={}".format(call))
for ids in range(0, r.json()['count']):
printFormatted(r.json()['results'][ids])
def main():
"""main function
Runs if script is run by itself."""
if len(sys.argv) <= 1:
# Check if arguments were given, if not, let the user
# input some here
arguments = []
userinput = input("No arguments found, enter them now: ")
words = userinput.split()
for word in words:
arguments.append(word)
else:
# If arguments were given, take them and move on
arguments = sys.argv[1:]
# Using these regex pattern to match agains valid DMRIDs
# and callsigns. The callsign pattern was taken from
# <https://gist.github.com/JoshuaCarroll/f6b2c64992dfe23feed49a117f5d1a43>
# and slighty modifed to also allow the percent sign (%) used by
# used by radioid.net as wildmask.
dmrid_userid_patt = re.compile("^[0-9]{7}$")
dmrid_rep_patt = re.compile("^[0-9]{6}$")
# dmrid_other_patt = re.compile("^[0-9]{0,5}$")
call_patt = re.compile("^[a-zA-Z0-9%]{1,3}[0123456789%][a-zA-Z0-9%]{0,2}[a-zA-Z%]$")
baseurl = 'https://www.radioid.net'
printHeaderLine()
for arg in arguments:
if dmrid_rep_patt.match(arg):
# A valid DMRID was found, so we have to lookup the
# callsign and we may get more DMRIDs for this RPT
# Valid means 6 chars long, all numbers. We do not know
# yet if the id really exists.
r = requests.get(baseurl + '/api/dmr/repeater/?id={}'.format(arg))
if r.status_code == 200:
# Only fetch more DMRIDs if the first one exists,
# otherwise we would try to run code on an non
# existing variable
getFromCallsign(baseurl, r.json()['results'][0]['callsign'])
elif dmrid_userid_patt.match(arg):
# A valid user ID was found. Valid means, technically
# correct -> 7 characters long, all numbers
print("{} looks like a user. Skipping for now.".format(arg))
# elif dmrid_other_patt.match(arg):
# # Print a warning for numbers less than 6 characters
# print("{} is not a valid dmr id!".format(arg))
elif call_patt.match(arg):
getFromCallsign(baseurl, arg)
else:
print('{} is an invalid value'.format(arg))
if __name__ == "__main__":
main()

47
savemail.sh Executable file
View file

@ -0,0 +1,47 @@
#!/bin/sh
#
# Saves an incoming email as plain text file (or .eml)
# somewhere in the webservers directories
# Author: Dominic Reich <quick.hat4396@qtztsjosmprqmgtunjyf.com>
# License: MIT
#umask 133
email="user@example.org"
date=`date +%Y%m%d-%H%M%S`
tmpf="/tmp/mail-$(echo ${date} | sha1).tmp"
folder="/var/www/htdocs/emails"
#cat $* > ${FILE}
while read line; do
case "$line" in
From:*|To:*|C[Cc]:*|Delivered-To:*|Date:*|Subject:*|Received:*|Message-ID:*|User-Agent:*) echo $line >> ${tmpf};;
"") (echo && cat $*) >> ${tmpf};;
*) ;;
esac
done
#SUBJECT="$(grep -i Subject ${TMPF} | awk -F': ' '{ print $2 }' | tr -cs "[:alnum:]" "-" | tr "äöüÄÖÜ" "aouAOU" | sed "s/-$//")"
#SUBJECT="$(grep -i "^Subject:" ${TMPF} | cut -d: -f2- | sed "s/^\ //" | tr -cs "[a-zA-z0-9äöüÄÖÜ]" "-" | tr "äöüÄÖÜ" "aouAOU" | sed "s/-$//" | qprint -d)"
# last sed: remove all "-" not only the last one, shrinks the name, but is not very readable...
# subject="$(grep -i "^Subject:" ${tmpf} | cut -d: -f2- | sed "s/^\ //" | tr -Cs "[:alnum:]" "-" | sed "s/-//g" | qprint -d)"
subject="$(grep -i "^Subject:" ${tmpf} | cut -d: -f2- | sed "s/^\ //" | tr -Cs "[:alnum:]" "-" | sed "s/-$//" | qprint -d)"
to="$(grep -i "^Delivered-To:" ${tmpf} | cut -d: -f2- | cut -d@ -f1 | xargs)"
#: "${VARIABLE:=DEFAULT_VALUE}"
: "${subject:=NoSubjectGiven}"
: "${to:=unknown}"
filename="${date}_${subject}.txt"
file="${folder}/${to}/${filename}"
link="http://bor.oe7drt.com/mailarchive/${to}/${filename}"
mv "${tmpf}" "${file}"
echo -e "New mail in archives: ${subject}\n\n<${link}>\n\n-- \nMail sorting script \`${0}\` to your service.\n" | \
mail -s "New mail in archives: ${to}" -- ${email}

77
send-suspicips.sh Executable file
View file

@ -0,0 +1,77 @@
#!/bin/sh
suspicfile=~/suspic
tmpfile=/tmp/ips
clean_up() {
echo -n "Removing tmp file..."
rm -f $tmpfile
rm -f $suspicfile
if [ "$?" -eq "0" ]; then
echo " done"
else
echo " *** FAILED ***"
echo "Could not delete tmp file \`$tmpfile\`"
exit 1
fi
}
# awk '{ print $1 }' $suspicfile | sort -h | uniq > ips
# Remove false-positives (like requests to the /posts URL which should be valid)
# I used some bad words in some filenames like "admin-panel..."
sed '/posts\//d' $suspicfile | awk '{ print $1 }' | sort -h | uniq > $tmpfile
ips_1=`wc -l $tmpfile | awk '{ print $1 }'`
#ip=`ifconfig | grep inet | egrep -v "inet6|127" | grep 0xffffff00 | awk '{ print $2 }'`
ip=`curl -s ifconfig.me`
echo "My remote ip address is $ip"
sed -i bak "/$ip/d" $tmpfile
ips_2=`wc -l $tmpfile | awk '{ print $1 }'`
removed_ips=`expr "$ips_1" - "$ips_2"`
echo "Removed $removed_ips ip address(es)"
echo -n "Inspecting ip file..."
ret="$(alacritty -e $EDITOR $tmpfile)"
if [ "$?" -eq "0" ]; then
echo " done"
else
echo " *** FAILED ***"
echo "Could not open editor. Aborting..."
clean_up
exit 1
fi
echo -n "Sending to openbsd-server..."
ret="$(scp -q $tmpfile openbsd-server:)"
if [ "$?" -eq "0" ]; then
echo " done"
else
echo " *** FAILED ***"
echo "Could not send the new ips to the OpenBSD server. Aborting..."
clean_up
exit 1
fi
echo -n "Sending to linux-server..."
ret="$(scp -q $tmpfile linux-server:)"
if [ "$?" -eq "0" ]; then
echo " done"
else
echo " *** FAILED ***"
echo "Could not send the new ips to the Archlinux server. Aborting..."
clean_up
exit 1
fi
clean_up
echo "Ok all done."

15
suspic-urls.sh Executable file
View file

@ -0,0 +1,15 @@
#!/bin/sh
EMAIL="user@example.org"
ACCESS_LOG="/tmp/suspic-access"
ERROR_LOG="/tmp/suspic-error"
egrep -h 'pma|admin|sql|w00t|CONNECT|wp-admin|wordpress|cgi-bin' /var/www/logs/access_log > ${ACCESS_LOG}
egrep -h 'client denied' /var/www/logs/error_log | grep 'server-status' > ${ERROR_LOG}
#cat ${ACCESS_LOG} | mail -s "Suspicious Webserver URLs" ${EMAIL}
#cat ${ERROR_LOG} | mail -s "Unauthorized server-status clients" ${EMAIL}
#rm ${ACCESS_LOG} ${ERROR_LOG}

43
tg.py Executable file
View file

@ -0,0 +1,43 @@
#!/usr/bin/env python3.11
"""look up TGs on brandmeister.network
"""
#import re # regex
import sys
#import argparse
import webbrowser
def main():
"""main function
Runs if script is run by itself."""
if len(sys.argv) <= 1:
# Check if arguments were given, if not, let the user
# input some here
arguments = []
userinput = input("Enter TG: ")
words = userinput.split()
for word in words:
arguments.append(word)
tg = arguments[0]
else:
# If arguments were given, take them and move on
tg = sys.argv[1]
if not isinstance(tg, int):
try:
tg = int(tg)
except:
print("Invalid value.")
exit(1)
url = "https://brandmeister.network/?page=lh&DestinationID={}".format(tg)
webbrowser.open(url, new=0, autoraise=True)
if __name__ == "__main__":
main()

35
update-blacklist-arch.sh Executable file
View file

@ -0,0 +1,35 @@
#!/bin/sh
# 2024-05-26
# Dominic Reich
BFILE=/srv/http/blocked.txt
if [[ $USER == "root" ]]; then
echo >&2 "User must not be root! Exiting"
exit 1
fi
while read ip; do sudo ipset -exist -A badips "$ip"; done < ~/ips
FILEBACKUP=14
if [ ${FILEBACKUP} -ne 0 ]; then
sudo cp ${BFILE} ${BFILE}.$(date +%Y%m%d)
fi
BACKUPCOUNT=$(ls ${BFILE}* | wc -l)
BACKUPSTODELETE=$(expr ${BACKUPCOUNT} - ${FILEBACKUP})
if [ ${BACKUPCOUNT} -gt ${FILEBACKUP} ]; then
for f in $(ls -tr ${BFILE}.* | head -${BACKUPSTODELETE})
do
sudo rm ${f}
done
fi
sudo ipset -output save -L | grep add | awk '{ print $3 }' | sort -g | sudo tee ${BFILE} 1>/dev/null
# Test if current ip is in the badips set
sudo ipset -q -T badips $(who | tail -1 | awk -F '[()]' '{ print $2 }')
sudo ipset --terse -L

42
update-blacklist-openbsd.sh Executable file
View file

@ -0,0 +1,42 @@
#!/bin/sh
#
# export the blacklist table from pf (pfctl -t blacklist)
# to the blocked.txt file on my http webroot
if [[ $USER == "root" ]]; then
echo >&2 "user must not be root! exiting."
exit 1
fi
# add ips to table blacklist
(for ip in `cat ~/ips`; do echo $ip;done) | xargs doas pfctl -t blacklist -T add
# save sorted table blacklist into file /etc/blacklist
doas pfctl -t blacklist -T show | sort -h|uniq | doas tee /etc/blacklist 1>/dev/null
# continue to update the blocked.txt file in the webserver root
# available at http://bor.oe7drt.com/blocked.txt
BLOCKEDTXT=/home/dominic/pub/blocked/web.txt
FILEBACKUP=7
if [ ${FILEBACKUP} -ne 0 ]; then
cp ${BLOCKEDTXT} ${BLOCKEDTXT}.$(date +%Y%m%d)
fi
BACKUPCOUNT=$(ls ${BLOCKEDTXT}.* | wc -l)
BACKUPSTODELETE=$(expr ${BACKUPCOUNT} - ${FILEBACKUP})
if [ ${BACKUPCOUNT} -gt ${FILEBACKUP} ]; then
for f in $(ls -tr ${BLOCKEDTXT}.* | head -${BACKUPSTODELETE})
do
rm ${f}
done
fi
doas pfctl -t blacklist -T show | tee ${BLOCKEDTXT} 1>/dev/null
doas pfctl -t blacklist -T test $(w | tail -1 | awk '{ print $3}')
doas pfctl -nf /etc/pf.conf
echo doas pfctl -vf /etc/pf.conf

27
update-webfai.sh Executable file
View file

@ -0,0 +1,27 @@
#!/bin/sh
# Update the TUXEDO WebFAI usb stick
# the file actually moved to https://webfai.tuxedocomputers.com/webfai-current.img
# hence the -L switch on curl
if (test -f *.iso); then
DATE=$(date +%Y%m%d-%H%M%S)
FILENAME=$(ls -1 *.iso)
BASENAME=$(basename ${FILENAME} .iso)
BACKUPFILE=${BASENAME}.backup-$DATE.iso
# backup old image
echo -n "Compressing old image file witz xz..."
xz -c ${FILENAME} > ${BACKUPFILE}.xz
echo "done"
else
echo "Found no iso file, no backup is made"
fi
echo -n "Downloading image file with curl..."
# download fresh image file
curl -sLO https://www.tuxedocomputers.com/webfai/webfai-nb/ipxe-stick-webfai-nb_current.iso
echo "done"

5
winlink-express.sh Executable file
View file

@ -0,0 +1,5 @@
#!/usr/bin/sh
# Start Winlink Express via Wine
WINEPREFIX=/home/dominic/.wine-winlink wine "C:\\RMS Express\\RMS Express.exe"

67
xbl-arch Executable file
View file

@ -0,0 +1,67 @@
#!/bin/sh
# Archlinux version
# integer scheck inspired from: https://stackoverflow.com/a/16444570
print_usage () {
echo >&2 "usage: $(basename ${0}) [0..100]"
exit 1
}
# check if argument given or not (list or set value)
if [ $# -eq 1 ]
then
# set value (select between ac or bat mode)
# check if argument is integer between 0,100
case $1 in
(*[!0-9]*|'')
print_usage
exit
;;
(*)
if [ "$1" -ge 0 ] && [ "$1" -le 100 ] 2>/dev/null
then
# argument given and between 0,100
case $( cat /sys/class/power_supply/AC/online ) in
(0) # BATTERY
echo "$1" > ${HOME}/.backlight-bat
;;
(1) # AC
echo "$1" > ${HOME}/.backlight-ac
;;
esac
blight set ${1}%
else
# arg not between 0 and 100
print_usage
fi
;;
esac
else
# no args given, only list values
case $( cat /sys/class/power_supply/AC/online ) in
(0) # BATTERY
current=bat
;;
(1) # AC
current=ac
;;
esac
# 100% 24242
for status in ac bat
do
if [ "${status}" = "${current}" ]
then
echo -e "${status}: ★ \t$( cat ${HOME}/.backlight-${status} )" | tr "[:lower:]" "[:upper:]"
else
echo -e "${status}:\t$( cat ${HOME}/.backlight-${status} )" | tr "[:lower:]" "[:upper:]"
fi
done
value=$(python -c "print(round(100/24242*`blight get`))")
echo -e "CUR:\t$(python -c "print($value)")"
fi

61
xbl-freebsd Executable file
View file

@ -0,0 +1,61 @@
#!/bin/sh
# FreeBSD version
print_usage () {
echo >&2 "usage: $(basename ${0}) [0..100]"
exit 1
}
# check if argument given or not (list or set value)
if [ $# -eq 1 ]
then
# set value (select between ac or bat mode)
# check if argument is integer between 0,100
if [ "$1" -eq "$1" ] 2>/dev/null
then
if [ "$1" -ge 0 ] && [ "$1" -le 100 ] 2>/dev/null
then
# argument given and between 0,100
case $( sysctl -n hw.acpi.acline ) in
(0) # BATTERY
echo "$1" > ${HOME}/.backlight-bat
;;
(1) # AC
echo "$1" > ${HOME}/.backlight-ac
;;
esac
backlight "$1"
else
# arg not between 0 and 100
print_usage
fi
else
# arg not an integer
print_usage
fi
else
# no args given, only list values
case $( sysctl -n hw.acpi.acline ) in
(0) # BATTERY
current=bat
;;
(1) # AC
current=ac
;;
esac
for status in ac bat
do
if [ "${status}" = "${current}" ]
then
echo -e "${status}: ★ \t$( cat ${HOME}/.backlight-${status} )" | tr "[:lower:]" "[:upper:]"
else
echo -e "${status}:\t$( cat ${HOME}/.backlight-${status} )" | tr "[:lower:]" "[:upper:]"
fi
done
echo -e "CUR:\t$(backlight | awk '{ print $2 }')"
fi

64
xbl-openbsd Executable file
View file

@ -0,0 +1,64 @@
#!/bin/sh
# OpenBSD version
# integer scheck inspired from: https://stackoverflow.com/a/16444570
print_usage () {
echo >&2 "usage: $(basename ${0}) [0..100]"
exit 1
}
# check if argument given or not (list or set value)
if [ $# -eq 1 ]
then
# set value (select between ac or bat mode)
# check if argument is integer between 0,100
case $1 in
(*[!0-9]*|'')
print_usage
exit
;;
(*)
if [ "$1" -ge 0 ] && [ "$1" -le 100 ] 2>/dev/null
then
# argument given and between 0,100
case $( sysctl -n hw.power ) in
(0) # BATTERY
echo "$1" > ${HOME}/.backlight-bat
;;
(1) # AC
echo "$1" > ${HOME}/.backlight-ac
;;
esac
doas wsconsctl display.brightness=$1
else
# arg not between 0 and 100
print_usage
fi
;;
esac
else
# no args given, only list values
case $( sysctl -n hw.power ) in
(0) # BATTERY
current=bat
;;
(1) # AC
current=ac
;;
esac
for status in ac bat
do
if [ "${status}" = "${current}" ]
then
echo -e "${status}: ★ \t$( cat ${HOME}/.backlight-${status} )" | tr "[:lower:]" "[:upper:]"
else
echo -e "${status}:\t$( cat ${HOME}/.backlight-${status} )" | tr "[:lower:]" "[:upper:]"
fi
done
echo -e "CUR:\t$(doas wsconsctl display.brightness | awk -F= '{ print $2 }')"
fi

39
xmon.sh Executable file
View file

@ -0,0 +1,39 @@
#!/bin/sh
# Practical script to adjust my monitor layout on ma X1 laptop
# Dominic Reich <quick.hat4396@qtztsjosmprqmgtunjyf.com>
internal="eDP-1"
external="HDMI-1"
print_usage () {
echo >&2 "usage: $(basename ${0}) [normal;wide;dup]"
exit 0
}
if [ $# -eq 1 ]
then
case "$1" in
"normal"|"n"|"norm")
xrandr --output "$external" --off --output "$internal" --auto
dunstify "Multimonitor setup" "set to normal ($internal)"
;;
"wide"|"w")
xrandr --output "$external" --set audio force-dvi --mode 1920x1080
xrandr --output "$internal" --auto --output "$external" --right-of "$internal"
dunstify "Multimonitor setup" "set to wide ($internal + $external (right-of))"
;;
"duplicate"|"dup"|"d")
xrandr --output "$external" --set audio force-dvi --mode 1920x1080
xrandr --output "$internal" --auto --output "$external" --same-as "$internal"
dunstify "Multimonitor setup" "set to duplicate ($internal; $external)"
;;
*)
dunstify -u critical "Multimonitor setup failed" "no such operation: ${1}"
;;
esac
else
print_usage
fi