1
0
mirror of https://github.com/kmein/niveum synced 2026-03-16 18:21:07 +01:00

10 Commits

Author SHA1 Message Date
b274a59a50 niri: add shortcut to float windows 2025-08-26 08:29:09 +02:00
b4de03bb3c replace more instances of rofi by wofi 2025-08-26 08:28:56 +02:00
b0062abbfe passmenu: fix 2025-08-26 07:50:31 +02:00
0e9a046c5f obsidian-vim: add fugitive 2025-08-26 07:50:24 +02:00
72ab319e65 niri: set window rules 2025-08-26 07:50:06 +02:00
f08e43067b configure niri 2025-08-26 07:19:54 +02:00
d0ac0af7c3 use wl-clipboard 2025-08-26 07:19:17 +02:00
5febabb7fa use wofi 2025-07-11 11:37:23 +02:00
44d29f90e9 working niri config 2025-07-10 06:51:51 +02:00
1aaf0fe5ae configure wayland for kabsa 2025-07-09 09:23:41 +02:00
347 changed files with 12861 additions and 8926 deletions

38
.bin/256color Executable file
View File

@@ -0,0 +1,38 @@
#! /bin/sh
set -euf
pl() {
for i in $(seq $1 $(expr $2 - 1)); do
printf '\e[38;5;%sm%03i\e[m ' $i $i
done
printf '\e[38;5;%sm%03i\e[m\n' $2 $2
}
p() {
printf '\e[38;5;%sm%03i\e[m ' $1 $1
}
pn() {
printf '\e[38;5;%sm%03i\e[m\n' $1 $1
}
p6x6() {
for i in $(seq 0 5); do
for j in $(seq 0 5); do
p $(expr $1 + $i + $j \* 6)
done
echo
done
}
pl 0 7
pl 8 15
p6x6 16
p6x6 52
p6x6 88
p6x6 124
p6x6 160
p6x6 196
pl 232 243
pl 244 255

29
.bin/anki-poem.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/sh
file="${1?please supply a poetry file}"
[ -f "$file" ] || {
echo "'$file' is no file"
exit 1
}
poem="$(mktemp)"
clean () {
rm "$poem"
}
trap clean EXIT
sed '/^$/d' "$file" > "$poem"
htmlize() {
awk 'ORS="<br/>"' \
| head -c -5 # remove final <br/> characters
}
for line_number in $(seq 1 "$(wc -l "$poem" | cut -d' ' -f1)"); do
if [ "$line_number" -gt 3 ] && [ "$line_number" -gt 1 ]; then
sed -n "$((line_number - 3)),$((line_number - 1))p" "$poem"
else
sed -n "1,$((line_number - 1))p" "$poem"
fi | htmlize
printf '\t'
sed -n "${line_number},+1p" "$poem" | htmlize
printf '\n'
done

54
.bin/avesta.sed Executable file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/env -S sed -f
s/ā̊/𐬃/g
s//𐬝/g
s/ṣ̌/𐬴/g
s/š́/𐬳/g
s/ą̄/𐬅/g
s/ŋᵛ/𐬤/g
s/ə̄/𐬇/g
s/ŋ́/𐬣/g
s//𐬒/g
s/xᵛ/𐬓/g
s/a/𐬀/g
s/ā/𐬁/g
s/å/𐬂/g
s/ą/𐬄/g
s/ə/𐬆/g
s/e/𐬈/g
s/ē/𐬉/g
s/o/𐬊/g
s/ō/𐬋/g
s/i/𐬌/g
s/ī/𐬍/g
s/u/𐬎/g
s/ū/𐬏/g
s/k/𐬐/g
s/x/𐬑/g
s/g/𐬔/g
s/ġ/𐬕/g
s/γ/𐬖/g
s/c/𐬗/g
s/j/𐬘/g
s/t/𐬙/g
s/θ/𐬚/g
s/d/𐬛/g
s/δ/𐬜/g
s/p/𐬞/g
s/f/𐬟/g
s/b/𐬠/g
s/β/𐬡/g
s/ŋ/𐬢/g
s/n/𐬥/g
s/ń/𐬦/g
s//𐬧/g
s/m/𐬨/g
s//𐬩/g
s//𐬫/g
s/y/𐬪/g
s/v/𐬬/g
s/r/𐬭/g
s/s/𐬯/g
s/z/𐬰/g
s/š/𐬱/g
s/ž/𐬲/g
s/h/𐬵/g

24
.bin/browser Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/sh -e
#
# Usage: browser
# pipe html to a browser
# e.g.
# $ echo '<h1>hi mom!</h1>' | browser
# $ ron -5 man/rip.5.ron | browser
if [ -t 0 ]; then
if [ -n "$1" ]; then
open $1
else
cat <<usage
Usage: browser
pipe html to a browser
$ echo '<h1>hi mom!</h1>' | browser
$ ron -5 man/rip.5.ron | browser
usage
fi
else
f="/tmp/browser.$RANDOM.html"
cat /dev/stdin > $f
xdg-open $f
fi

46
.bin/bvg.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/bin/sh
interesting="U6 N6 140 M46 184 N84"
curl -sSL 'https://www.bvg.de/disruption-reports/q' \
--data-raw '{"variables":{},"query":"{
allDisruptions {
disruptions {
meldungsId
linie
verkehrsmittel
__typename
... on Traffic {
datum
gueltigVonDatum
gueltigVonZeit
gueltigBisDatum
gueltigBisZeit
richtungName
richtungHafasId
beginnAbschnittName
beginnAbschnittHafasId
endeAbschnittName
endeAbschnittHafasId
textIntUrsache
sev
textIntAuswirkung
umfahrung
textWAPSMSUrsache
textWAPSMSAuswirkung
prioritaet
__typename
}
}
__typename
}
}"}' \
| jq --arg interesting "$interesting" '
.data.allDisruptions.disruptions
| map(select(
(.linie as $linie
| $interesting
| split(" ")
| index($linie))
and (.["__typename"] == "Traffic")
))
'

19
.bin/calendars.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/sh
directory="$(mktemp -d)"
trap clean EXIT
clean() {
rm -rf "$directory"
}
year=$(date +%Y)
output=/tmp/$year.pdf
for month in $(seq 1 12); do
printf "\r%d" "$month" 1>&2
astrolog -zN Berlin -qm "$month" "$year" -X -K -XA -Xr -Xm -Xb -Xo "$(printf "%s/%02d.bmp" "$directory" "$month")" -Xw 1080 720 2>/dev/null
done
printf "\r"
convert "$directory/*.bmp" "$output"
echo "$output"

25
.bin/candyman Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/sh
set -efu
usage() {
echo >&2 "$0 add-{reddit,telegram,youtube,twitch,twitter} NAME"
exit 1
}
candyman() {
curl -fsSv http://news.r/api -H content-type:application/json -d "$(jq -n "
{
command: \"PRIVMSG\",
params: [\"#all\", \"candyman: $1 $2\"]
}
")"
}
[ $# -ge 2 ] || usage
case "$1" in
add-reddit|add-telegram|add-youtube|add-twitter|add-twitch)
candyman "$@"
;;
*) usage;;
esac

23
.bin/chunk-pdf Executable file
View File

@@ -0,0 +1,23 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p pdftk gnugrep
set -efu
INPUT_FILE="${2:?Pass the PDF path as second argument.}"
PAGES_PER_REPORT="${1:?Pass the chunk size as first argument.}"
if [ ! -f "$INPUT_FILE" ]; then
echo >&2 "File $INPUT_FILE does not exist."
exit 1
fi
TOTAL_PAGES="$(pdftk "$INPUT_FILE" dump_data | grep NumberOfPages | cut -f2 -d' ')"
RUNS=$((TOTAL_PAGES/PAGES_PER_REPORT))
for run in $(seq 0 "$((RUNS-1))"); do
start_page=$((run*PAGES_PER_REPORT+1))
end_page=$(((run+1)*PAGES_PER_REPORT))
output_file="chunk_$((run+1)).pdf"
echo "splitting $INPUT_FILE from $start_page to $end_page into $output_file"
pdftk "$INPUT_FILE" cat "$start_page-$end_page" output "$output_file"
done

13
.bin/countdown Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env -S awk -f
function z() {
getline < "/proc/uptime"
close("/proc/uptime")
return $0
}
BEGIN {
x = z()
while (1) {
y = z()
printf "%02d:%05.2f\r", (y - x) / 60, (y - x) % 60
}
}

14
.bin/csv2json Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env python3
import csv
import json
import sys
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--delimiter", "-d", default=",", help="CSV field separator")
args = parser.parse_args()
if __name__ == "__main__":
json.dump(list(csv.DictReader(sys.stdin, delimiter=args.delimiter)), sys.stdout)

43
.bin/dummy-alert Executable file
View File

@@ -0,0 +1,43 @@
#!/bin/bash
name=$RANDOM
url='http://localhost:9093/api/v1/alerts'
echo "firing up alert $name"
# change url o
curl -XPOST $url -d "[{
\"status\": \"firing\",
\"labels\": {
\"alertname\": \"$name\",
\"service\": \"my-service\",
\"severity\":\"warning\",
\"instance\": \"$name.example.net\"
},
\"annotations\": {
\"summary\": \"High latency is high!\"
},
\"generatorURL\": \"http://prometheus.int.example.net/<generating_expression>\"
}]"
echo ""
echo "press enter to resolve alert"
read
echo "sending resolve"
curl -XPOST $url -d "[{
\"status\": \"resolved\",
\"labels\": {
\"alertname\": \"$name\",
\"service\": \"my-service\",
\"severity\":\"warning\",
\"instance\": \"$name.example.net\"
},
\"annotations\": {
\"summary\": \"High latency is high!\"
},
\"generatorURL\": \"http://prometheus.int.example.net/<generating_expression>\"
}]"
echo ""

7
.bin/elm-publish-private Executable file
View File

@@ -0,0 +1,7 @@
#! /usr/bin/env nix-shell
#! nix-shell -p "(import <nixpkgs> { overlays = [ (import ~/work/fysiweb/engiadina-pwa/devops/pkgs) ]; }).elm-publish-private"
#! nix-shell -i bash
set -efux
exec elm-publish-private "$@"

21
.bin/fix-sd.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
set -xfu
drive="$1"
mountpoint="/media/sd-card-$(date +%s)"
backup_directory="$(pwd)"
trap clean EXIT
clean() {
umount "$mountpoint"
rmdir "$mountpoint"
fsck.exfat "$drive"
}
filenames="$(fsck.exfat "$drive" 2>&1 | sed -nE "s/.* file '(.*?)' is not allocated.*/\1/p")"
mkdir "$mountpoint"
mount "$drive" "$mountpoint"
echo "$filenames" | while read -r filename; do
find "$mountpoint" -type f -name "$filename" -exec mv {} "$backup_directory" \;
done

34
.bin/horoscope.sh Normal file
View File

@@ -0,0 +1,34 @@
#!/bin/sh
set -efu
# Berlin: -d lodeg=13 -d lomin=22 -d losec=41 -d lodir=E -d ladeg=52 -d lamin=27 -d lasec=42 -d ladir=N -d usecoords=1 \
# Kassel: -d lodeg=9 -d lomin=32 -d losec=5 -d lodir=E -d ladeg=51 -d lamin=18 -d lasec=17 -d ladir=N -d usecoords=1 \
[ $# -eq 1 ] || {
echo >&2 Usage: "$0" TIMESTAMP
exit 1
}
export TZ=UTC
chart_path="$(mktemp /tmp/chart_XXX.pdf)"
timestamp="$1"
year="$(date -d "@$timestamp" +%Y)"
month="$(date -d "@$timestamp" +%m)"
day="$(date -d "@$timestamp" +%d)"
hour="$(date -d "@$timestamp" +%H)"
minute="$(date -d "@$timestamp" +%M)"
curl -sSL 'https://edifyingfellowship.org/astro/' \
-d lodeg=9 -d lomin=32 -d losec=5 -d lodir=E -d ladeg=51 -d lamin=18 -d lasec=17 -d ladir=N -d usecoords=1 \
-d ybyr="$year" -d ybmo="$month" -d ybdy="$day" -d ybhr="$hour" -d ybmi="$minute" -d ybsc=0 -d ybtz="$TZ" \
-d currenttime=0 \
-d title="$timestamp" \
-d options[]=VancouverWheel -d options[]=Arrow -d options[]=XBold -d options[]=HouseLabels -d options[]=Placidus \
-d options[]=Sun -d options[]=Moon -d options[]=Mercury -d options[]=Venus -d options[]=Mars -d options[]=Jupiter -d options[]=Saturn -d options[]=Uranus -d options[]=Neptune -d options[]=Pluto -d options[]=Ascendant -d options[]=MC -d options[]=Lilith -d options[]=MeanNode -d options[]=TrueNode \
-d aspectpct=100 -d format=PDF -d Submit= -o "$chart_path"
zathura "$chart_path"

24
.bin/json2csv Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env python3
import csv
import json
import sys
if __name__ == "__main__":
json_list = json.load(sys.stdin)
if not isinstance(json_list, list):
print("JSON object is not a list.", file=sys.stderr)
sys.exit(1)
if len(json_list) == 0:
print("JSON list is empty.", file=sys.stderr)
sys.exit(1)
keys = set()
for element in json_list:
if isinstance(element, dict):
keys |= element.keys()
else:
print("Non-dict element:", element, file=sys.stderr)
sys.exit(1)
writer = csv.DictWriter(sys.stdout, fieldnames=list(keys))
writer.writeheader()
for element in json_list:
writer.writerow(element)

5
.bin/json2csv.jq Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env -S jq -r -f
(map(keys) | add | unique) as $cols
| map(. as $row | $cols | map($row[.])) as $rows
| $cols, $rows[]
| @csv

15
.bin/libib.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/env bash
session_id=7b638c194d9bda74f80043045018cc9e
declare -A libraries
libraries["Literatur"]=344428
libraries["Sprache"]=344160
libraries["Miscellanea"]=344427
libraries["Wissenschaft"]=344429
libraries["Relicta"]=565920
for library in ${!libraries[@]}
do
curl -sSL 'https://www.libib.com/library/functions/csv-export.php' -H "Cookie: PHPSESSID=$session_id" -d export="${libraries[$library]}" > "$library.csv"
done

81
.bin/lieferando.sh Normal file
View File

@@ -0,0 +1,81 @@
#!/bin/sh
set -efu
if echo "$1" | grep -Eq '[[:digit:]]{5}'; then
PLZ="$1"
else
echo >&2 "Usage: $0 PLZ"
exit 1
fi
lieferando_dir=/tmp/lieferando
mkdir -p "$lieferando_dir/$PLZ"
fetch_restaurants() {
cache_path="$lieferando_dir/$PLZ.json"
if [ -r "$cache_path" ]; then
cat "$cache_path"
else
w3m -dump_source "http://www.lieferando.de/$PLZ" \
| gunzip \
| sed -n '/var restaurants/,/];$/p' \
| sed 's/var restaurants =//;$s/;$//' \
| prettier --parser=json \
| jq '
map({
name: .[30] | .name,
category: .[30] |.categories | split(", "),
url: "http://lieferando.de\(.[30] | .url)",
minutes: .[19],
minimum: .[10],
delivery: .[14]
})' \
| tee "$cache_path"
fi
}
fetch_menu() {
[ $# -eq 1 ] || exit 1
slug="$(echo "$1" | sed 's!.*/!!')"
cache_path="$lieferando_dir/$PLZ/$slug.json"
if [ -r "$cache_path" ]; then
cat "$cache_path"
else
w3m -dump_source "$1" \
| gunzip \
| sed -n '/var MenucardProducts/,/\];/p' \
| sed 's/var MenucardProducts =//;s/;$//' \
| jq -r '
unique_by(.productId)
| group_by(.categoryId)
| flatten
' \
| tee "$cache_path"
fi
}
data="$(fetch_restaurants)"
# echo "$data" | jq -c '.[]' | while read -r restaurant; do
# fetch_menu "$(echo "$restaurant" | jq -r .url)"
# done
selected_categories="$(echo "$data" | jq -r 'map(.category) | flatten | unique | .[]' | fzf -m)"
selected_restaurant_url="$(echo "$selected_categories" | jq --argjson restaurants "$data" -sRr '
split("\n")[:-1] as $categories
| $restaurants[]
| select(.category - $categories != .category)
| "\(.name) [🚴\(.minutes)min 💰\(.minimum)€ + \(.delivery)€] (\(.url))"
' \
| fzf \
| sed 's/.*(//;s/)$//'
)"
fetch_menu "$selected_restaurant_url" \
| jq -r '.[] | "\(.price)\t\(.name)"' \
| fzf -m \
| awk '{print $0; sum += $1} END {print "-----"; print sum}'

17
.bin/lit.awk Normal file
View File

@@ -0,0 +1,17 @@
BEGIN {
if (!comment) comment = "--";
if (!begin) begin = "\\begin{code}";
if (!end) end = "\\end{code}";
}
{
if ($0 == begin) {
code = 1;
print comment, $0;
} else if ($0 == end) {
code = 0;
print comment, $0;
} else {
if (code) print $0;
else print comment, $0;
}
}

3
.bin/mail-current-part Executable file
View File

@@ -0,0 +1,3 @@
#! /bin/sh
set -efu
exec curl -fSs --unix-socket /tmp/much.api.sock http://localhost/current/part

View File

@@ -0,0 +1,27 @@
#! /bin/sh
# usage: mail-current-query-find-part-by-name NAME
set -efu
name=$1
query=$(mail-current-query)
result=$(notmuch show --entire-thread=false --format=json "$query")
part_id=$(printf %s "$result" | jq --arg name "$name" '
[
recurse |
select(type == "object") |
{ id, name: .filename } |
select(.id != null and .name != null)
] |
map(select(.name == $name))[0].id
')
if test "$part_id" = null; then
printf 'error: could not find part with name %s\n' \
"$name" \
>&2
exit 1
fi
exec notmuch show --part="$part_id" "$query"

View File

@@ -0,0 +1,39 @@
#! /bin/sh
# usage: mail-current-query-find-part-by-type TYPE
set -efu
type=$1
query=$(mail-current-query)
result=$(notmuch show --entire-thread=false --format=json "$query")
part_id=$(printf %s "$result" | jq --arg type "$type" '
#flatten|map(select(.!=null))[0].body[0] |
#
#if .["content-type"] == $type then
# .id
#elif .["content-type"] | test("^multipart/") then
# .content|map(select(.["content-type"]==$type))[0].id
#else
# null
#end
[
recurse |
select(type == "object") |
{ id, type: .["content-type"] } |
select(.id != null and .type != null)
] |
map(select(.type == $type))[0].id
')
if test "$part_id" = null; then
printf 'error: could not find part with type %s\n' \
"$type" \
>&2
exit 1
fi
exec notmuch show --part="$part_id" "$query"

1
.bin/mud.sh Executable file
View File

@@ -0,0 +1 @@
ssh mud@hotdog.r -t "MUD_NICKNAME=$LOGNAME mud"

6
.bin/mushakkil.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
curl -sSL 'https://diac.alsharekh.org/Diac/DiacText' \
-H "Content-Type: application/json" \
--data-raw "$(jq --raw-input '{word: ., type: 1}')" \
--compressed \
| jq -r .diacWord

93
.bin/nix-haddock-index Executable file
View File

@@ -0,0 +1,93 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p coreutils gnugrep gnused graphviz
#
# usage: nix-haddock-index
#
# Run this script in an environment where either NIX_GHC is set, or the ghc
# executable exists, to generate an HTML index file pointing to all Haddock
# files accessible to the respective ghc version.
#
# Additionally, an SVG dependency graph of all packages is linked at the
# bottom of the index file.
#
# Note: all files will be generated in /tmp, and won't be deleted automatically
#
set -efux
if test -z "${NIX_GHC-}"; then
NIX_GHC=$(readlink -f "$(type -P ghc)")
fi
if ! echo $NIX_GHC | grep -q '^/nix/store/'; then
printf '%s: error: unsupported GHC executable path (not in Nix store): %q\n' \
"$0" \
"$NIX_GHC" \
>&2
exit -1
fi
NIX_GHC_PREFIX=$(dirname "$(dirname "$NIX_GHC")")
NIX_GHC_DOCDIR=$NIX_GHC_PREFIX/share/doc/ghc/html
main() {
hash=$(echo $NIX_GHC_PREFIX | sed -n 's|^/nix/store/\([a-z0-9]\+\).*|\1|p')
title="Haddock index for $NIX_GHC_PREFIX"
header=$(
printf 'Haddock index for <a href="%s">%s</a>\n' \
$NIX_GHC_PREFIX \
$NIX_GHC_PREFIX \
)
suffix=${hash:+-$hash}
index_file=/tmp/haddock$suffix-index.html
svg_file=/tmp/haddock$suffix.svg
#if ! test -e $index_file; then
eval "$(
echo 'gen_index() {'
echo ' html_head'
"$NIX_GHC_PREFIX"/bin/ghc-pkg dump | sed -n '
s/^---$/ reset/p
s/^\(name\|version\):\s*\([-A-Za-z0-9_.]\+\)$/ \1=\2/p
s/^haddock-html:\s*\([-A-Za-z0-9_./]\+\)$/ haddock_html \1/p
'
echo ' html_foot'
echo '}'
)"
gen_index > $index_file
#fi
#if ! test -e $svg_file; then
"$NIX_GHC_PREFIX"/bin/ghc-pkg dot | tred | dot -Tsvg | sed '
s/<svg width="[0-9]\+pt" height="[0-9]\+pt"/<svg width="3600px" height="100%"/
' > $svg_file
#fi
echo $index_file
}
reset() {
unset name version
}
haddock_html() {
printf '<li>'
printf '<a href="%s/index.html">%s</a>' "$1" "$name-$version"
printf '</li>\n'
}
html_head() {
printf '<!doctype html>\n'
printf '<title>%s</title>\n' "$title"
printf '<link href="%s" rel="stylesheet" type="text/css">\n' \
"$NIX_GHC_DOCDIR/libraries/ocean.css"
printf '<h1>%s</h1>\n' "$header"
printf '<ul>\n'
}
html_foot() {
printf '</ul>\n'
printf '<a href="%s">graph</a>\n' "$svg_file"
}
main "$@"

15
.bin/notetags.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
# inspired by https://github.com/connermcd/bin/blob/1d38cb98812906d8b95dc6e51e1149e29261617d/notetags
cd "$HOME/notes/" || exit
[ -f tags ] && rm tags
grep -r 'tags:' ./* | while read -r line; do
file=$(echo "$line" | cut -d: -f1)
unparsed_tags=$(echo "$line" | cut -d: -f3) #
tags=$(echo "$unparsed_tags" | sed -e 's/tags: *//g' -e 's/[][,]//g')
for tag in $tags; do
echo "$tag $file /^$unparsed_tags$/;" >> tags
done
done

23
.bin/pdf-ocr.sh Executable file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env nix-shell
#! nix-shell -i bash -p poppler_utils tesseract4
set -eu
pdf_path="$(realpath "$1")"
[ -f "$pdf_path" ] || {
echo "Usage: $0 FILE.pdf" >&2
exit 1
}
tmpdir="$(mktemp -d)"
trap 'rm -rf $tmpdir' EXIT
cd "$tmpdir"
pdftoppm -png "$pdf_path" pdf-ocr
for png in pdf-ocr*.png; do
tesseract "$png" "$png.txt" 2>/dev/null
done
cat pdf-ocr-*.txt

2
.bin/playlist_entries.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
youtube-dl -ij "$*" | jq -sr '.[] | .webpage_url'

65
.bin/prospekte.sh Executable file
View File

@@ -0,0 +1,65 @@
#!/bin/sh
lidl() {
echo LIDL
curl -sSL 'https://endpoints.lidl-flyer.com/v3/region-overview/lidl/de-DE/0.json' \
| jq -r '
.categories
| map(select(.name == "Filial-Angebote") | .subcategories | map(.flyers))
| flatten
| flatten
| .[]
| .pdfUrl
'
}
aldi_nord() {
echo ALDI nord
echo 'https://magazine.aldi-nord.de/aldi-nord/aldi-aktuell/GetPDF.ashx'
echo 'https://magazine.aldi-nord.de/aldi-nord/aldi-vorschau/GetPDF.ashx'
}
rewe_berlin() {(
store_id=662366923
publisher_id=1062
echo REWE
curl -sSL 'https://www.bonialserviceswidget.de/de/stores/'$store_id'/brochures?storeId='$store_id'&publisherId='$publisher_id | while read -r brochure_id; do
curl -sSL 'https://www.bonialserviceswidget.de/de/v5/brochureDetails/'"$brochure_id"'?publisherId='$publisher_id | jq -r .pdfUrl
done
)}
kaufland() {(
region_code=8920
echo KAUFLAND
curl -sSL https://filiale.kaufland.de/prospekte.html | htmlq --attribute href '.flyer a' | grep -Eo 'DE_de_KDZ[^/]*' | sed "s/_3000_/_${region_code}_/" | while read -r flyer_id; do
curl -sSL "https://endpoints.leaflets.kaufland.com/v3/$flyer_id/flyer.json?regionCode=$region_code" | jq -r .flyer.pdfUrl
done
)}
netto_schwarz() {
echo 'NETTO (schwarz)'
curl -sSL 'https://squid-api.tjek.com/v2/catalogs?dealer_ids=90f2VL&order_by=created' \
| jq -r '.[] | .id' \
| while read -r flyer_id; do
curl -sSL "https://squid-api.tjek.com/v2/catalogs/$flyer_id/download" \
| jq -r .pdf_url
done
}
dir="$(mktemp -d)"
trap clean EXIT
clean() {
rm -rf "$dir"
}
prospekt_url="$( (
lidl
aldi_nord
rewe_berlin
kaufland
netto_schwarz
) | fzf)"
curl -sSL "$prospekt_url" -o "$dir/prospekt.pdf"
zathura "$dir/prospekt.pdf"

17
.bin/proxies.sh Normal file
View File

@@ -0,0 +1,17 @@
#!/bin/sh
curl -sSL https://www.netzwelt.de/proxy/index.html \
| pup ".tblc" \
| xml-to-json /dev/stdin \
| jq '
.div.table.tbody.tr
| map(
.td
| {
ip: .[0].a.value,
port: .[1],
country: .[2] | (if type == "string" then . else .a.value end),
security: .[3],
protocol: .[4]
}
)
'

4
.bin/readme Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
curl -sSL "https://raw.githubusercontent.com/$*/master/README.md" \
| pandoc -f gfm -t man -s \
| man -l -

6
.bin/sample-pdf.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
filepath="$(shuf --head-count=1)"
pages="$(pdfinfo "$filepath" | awk '/^Pages:/{print $2}')"
random_page="$(shuf --input-range="1-$pages" --head-count=1)"
zathura --page="$random_page" "$filepath"

16
.bin/screencap.sh Executable file
View File

@@ -0,0 +1,16 @@
#! /usr/bin/env nix-shell
#! nix-shell -i sh -p coreutils byzanz xorg.xwininfo gnused
# shellcheck shell=sh
# ref https://gist.github.com/aforemny/0994cb7f06ea30d56c8b9681ff5d2054
set -eux
eval "$(xwininfo | \
sed -n -e 's/^ \+Absolute upper-left X: \+\([0-9]\+\).*/x=\1/p' \
-e 's/^ \+Absolute upper-left Y: \+\([0-9]\+\).*/y=\1/p' \
-e 's/^ \+Width: \+\([0-9]\+\).*/w=\1/p' \
-e 's/^ \+Height: \+\([0-9]\+\).*/h=\1/p')"
trap "pkill -f 'sleep 360d'" INT
byzanz-record -e "sleep 360d" -c -x $x -y $y -w $w -h $h "$@"

49
.bin/space.py Normal file
View File

@@ -0,0 +1,49 @@
import ephem
from datetime import datetime, date, timedelta
now = datetime.now()
limit = now + timedelta(days=365)
def events_until(limit):
initial_date = ephem.Date(datetime.now())
events = {}
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_full_moon(now)
events[now] = "🌕"
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_new_moon(now)
events[now] = "🌑"
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_vernal_equinox(now)
events[now] = "spring equinox"
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_autumnal_equinox(now)
events[now] = "fall equinox"
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_winter_solstice(now)
events[now] = "winter solstice"
now = initial_date
while ephem.localtime(now) <= limit:
now = ephem.next_summer_solstice(now)
events[now] = "summer solstice"
return events
events = events_until(limit)
for date, event in sorted(events.items(), key=lambda x: x[0]):
if ephem.localtime(date) < limit:
print(ephem.localtime(date), event)

50
.bin/toposort.nix Normal file
View File

@@ -0,0 +1,50 @@
let
lib = import <nixpkgs/lib>;
in rec {
inherit lib;
input = [
{
x = ["pool" "zfs"];
y = ["mdadm" "raid1"];
}
{
x = ["pool" "zfs"];
y = ["disk" "sda"];
}
{
x = ["mdadm" "raid1"];
y = ["disk" "sdb"];
}
{
x = ["mdadm" "raid1"];
y = ["disk" "sdc"];
}
];
outNodes = node: graph:
lib.unique
(builtins.map (e: e.y)
(builtins.filter (v: v.x == node) graph));
vertices = graph:
lib.unique
(builtins.map (x: x.y) graph ++ builtins.map (x: x.x) graph);
deleteVertex = node: graph: (builtins.filter (v: v.x != node && v.y != node) graph);
findSink = graph:
lib.findFirst
(v: outNodes v graph == [])
(lib.trace graph (builtins.abort "No sink found"))
(vertices graph);
topSort = graph:
if graph == []
then []
else if builtins.length graph == 1
then let only = builtins.head graph; in [only.y only.x]
else let sink = findSink graph; in [sink] ++ topSort (deleteVertex sink graph);
output = topSort input;
}

18
.bin/ttrss-unread Executable file
View File

@@ -0,0 +1,18 @@
#/usr/bin/env -S deno run -A:q
set -x
session_cache="$HOME/.cache/tt-rss.session"
ttrss_endpoint=https://feed.kmein.de/api/
ttrss_user=k
ttrss_password=$(pass shared/tt-rss/password)
login() {
if [ -f "$session_cache" ]; then
session_id="$(cat "$session_cache")"
else
session_id="$(curl -d '{"op":"login","user":"'"$ttrss_user"'","password":"'"$ttrss_password"'"}' "$ttrss_endpoint" | jq -r .content.session_id)"
echo "$session_id" > "$session_cache"
fi
}
login
curl -d '{"sid":"'"$session_id"'","op":"getUnread"}' "$ttrss_endpoint" | jq .content

16
.bin/tuesday-1800 Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/sh
set -efux
expected_max_results=1024 # the upper bound on the number of restaurants
radius=250
echo '[out:json];node(id:260050809)->.cbase;
(
node(around.cbase:'$radius')[amenity=fast_food];
node(around.cbase:'$radius')[amenity=restaurant];
);out;' \
| curl -sSL -d @- -X POST http://overpass-api.de/api/interpreter \
| jq --argjson random "$(shuf -i 0-$expected_max_results -n 1)" '
.elements
| length as $length
| .[$random % $length]
'

8
.bin/unicode Normal file
View File

@@ -0,0 +1,8 @@
import sys
import unicodedata
for index, character in enumerate(sys.stdin.read().strip()):
try:
print(index, character, hex(ord(character)), unicodedata.category(character), unicodedata.name(character))
except:
print(index, character, hex(ord(character)))

26
.bin/watson2fdf.sh Executable file
View File

@@ -0,0 +1,26 @@
project=Filli
year=2022
for month in Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec; do
from="$(date +%F -d "$month 1, $year")"
to="$(date +%F -d "$month 1, $year + 1 month")"
watson report --json --from "$from" --to "$to" --project "$project"
done | jq --slurp '
def in_array($arr):
. as $value | any($arr[]; . == $value);
map(
["engadin-app","fysiweb","val-muestair","mia-engiadina","ol"] as $official_projects
| (.timespan.from | .[0:7]) as $timespan
| .projects | .[0]
| .time as $total_time
| .tags
| select(. != null)
| map(select(.name | in_array($official_projects)))
| (map(.time)|add) as $official_time
| map({key:.name, value:.time}) | from_entries
| .other |= ($total_time - $official_time)
| map_values(. / (60*60) | ceil)
| .month |= $timespan
)
'

View File

@@ -2,7 +2,7 @@ name: Update flake.lock
on:
workflow_dispatch: # allows manual triggering
schedule:
- cron: "0 0 * * 0" # runs weekly on Sunday at 00:00
- cron: '0 0 * * 0' # runs weekly on Sunday at 00:00
jobs:
lockfile:

View File

@@ -7,33 +7,33 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
system: [makanek, manakish, kabsa, zaatar, ful, fatteh]
system: [makanek,manakish,kabsa,zaatar,ful,fatteh]
steps:
- uses: actions/checkout@v3
- name: Install QEMU (ARM)
run: |
sudo apt-get update
sudo apt-get install -y qemu-user-static
if: ${{ matrix.system == 'ful' }}
- name: Install Nix (ARM)
uses: cachix/install-nix-action@v16
if: ${{ matrix.system == 'ful' }}
with:
extra_nix_config: |
system = aarch64-linux
- name: Install Nix (x86_64)
uses: cachix/install-nix-action@v16
if: ${{ matrix.system != 'ful' }}
- name: nixos-rebuild dry-build
run: |
# remove secrets: ref https://stackoverflow.com/questions/1260748/how-do-i-remove-a-submodule/36593218
git submodule deinit -f secrets
rm -rf .git/modules/secrets
git rm -f secrets
- uses: actions/checkout@v3
- name: Install QEMU (ARM)
run: |
sudo apt-get update
sudo apt-get install -y qemu-user-static
if: ${{ matrix.system == 'ful' }}
- name: Install Nix (ARM)
uses: cachix/install-nix-action@v16
if: ${{ matrix.system == 'ful' }}
with:
extra_nix_config: |
system = aarch64-linux
- name: Install Nix (x86_64)
uses: cachix/install-nix-action@v16
if: ${{ matrix.system != 'ful' }}
- name: nixos-rebuild dry-build
run: |
# remove secrets: ref https://stackoverflow.com/questions/1260748/how-do-i-remove-a-submodule/36593218
git submodule deinit -f secrets
rm -rf .git/modules/secrets
git rm -f secrets
# recreate secrets
mkdir secrets
cat secrets.txt | while read -r path; do touch $path; done
git add secrets
# recreate secrets
mkdir secrets
cat secrets.txt | while read -r path; do touch $path; done
git add secrets
nix run nixpkgs#nixos-rebuild -- dry-build --flake $GITHUB_WORKSPACE#${{matrix.system}}
nix run nixpkgs#nixos-rebuild -- dry-build --flake $GITHUB_WORKSPACE#${{matrix.system}}

View File

@@ -1,96 +0,0 @@
# niveum — Agent Notes
## What This Is
A NixOS flake managing ~9 machines (desktops, servers, family laptops) for one user (kmein/kfm).
Levantine food-themed hostnames: fatteh, kabsa, kibbeh, makanek, manakish, tabula, tahina, zaatar, ful.
## Repository Structure
```
flake.nix # ~670 lines — inputs, overlay, nixosConfigurations, apps, packages output
configs/ # ~50 NixOS config fragments imported by systems
default.nix # 200+ line mega-module for desktop machines (user, shell, gnupg, i18n, etc.)
graphical/ # Hyprland + home-manager config (415 lines in home-manager.nix)
packages.nix # ~250 lines of environment.systemPackages
bots/ # Telegram/Mastodon/Matrix bot configs
keyboard/ # XKB layouts (Coptic, Avestan, Gothic, etc.)
configs/*.nix # Individual concerns: bluetooth, sound, printing, ssh, fonts, etc.
modules/ # Proper NixOS modules with options (retiolum, telegram-bot, passport, power-action, etc.)
packages/ # ~107 package files (scripts, wrappers, small tools)
systems/<name>/ # Per-machine: configuration.nix + hardware-configuration.nix + extras
lib/ # default.nix (niveum helpers), machines.nix (IP/key inventory), panoptikon.nix
secrets/ # agenix-encrypted .age files (empty dir in checkout, tracked via secrets.txt)
```
## Key Relationships
- **niphas** (input): Provides shared "how I like things" config — nixosModules (shell, editor, git, desktop, nix, udiskie) and overlay (niphas-* packages). Used in `profiles.default` and `profiles.desktop`.
- **configs/default.nix**: The "big desktop profile" — imported by fatteh, kabsa, manakish (the main desktop machines). NOT imported by servers or family laptops.
- **profiles** (in flake.nix): `profiles.default`, `profiles.desktop`, `profiles.server` — lists of modules composed per machine.
- **lib.niveum**: Custom lib injected via overlay (`pkgs.lib.niveum`) — used everywhere for machine addresses, SSH port, helper functions.
## Coding Conventions
- Packages use `writers.writeDashBin`, `writers.writeBashBin`, or `writers.writePython3Bin`
- Dependencies are referenced via `lib.getExe pkg` (main executable) or `lib.getExe' pkg "name"` (specific binary)
- For packages needing many commands via PATH, use `lib.makeBinPath` instead (see `packages/prospekte.nix`)
- Overlay entries use `prev.callPackage packages/foo.nix { }` pattern
- Packages are exported via `inherit (pkgs) ...` in the `packages` output
## Known Bugs / Broken References
All previously broken references have been fixed (see commits `36132b04`, `e67d6d7d`).
Remaining issues:
- `modules/retiolum.nix` uses `<retiolum/hosts>` and `<system-secrets/...>` NIX_PATH lookups — breaks flake purity but works with current `NIX_PATH` setup
## Architectural Issues
### 1. configs/default.nix is a grab-bag (200+ lines, ~15 inline anonymous modules)
It's a list of `imports` mixing inline `{ ... }` blocks with file imports. Hard to find what's defined where.
### 2. Retiolum secret boilerplate repeated 9 times
Every system has a near-identical block:
```nix
age.secrets.retiolum-rsa = { file = ../../secrets/${hostname}-retiolum-privateKey-rsa.age; mode = "400"; owner = "tinc-retiolum"; ... };
age.secrets.retiolum-ed25519 = { ... same ... };
```
Could be a function or module parameterized by hostname.
### 3. Nginx + ACME boilerplate duplicated
ful and makanek have identical nginx recommended settings + ACME config.
### 4. niveum-* overlay aliases
`niveum-terminal`, `niveum-browser`, `niveum-filemanager` are aliases to niphas equivalents. Could be removed by updating ~6 references in configs/ to use niphas-* names directly.
### 5. The `pkgs.lib.niveum` pattern
Custom lib injected via overlay into `pkgs.lib`. Unconventional — only available where overlay is applied. A `specialArgs` approach or standalone lib would be cleaner.
### 6. Restic backup config scattered
`services.restic.backups.niveum` is configured in configs/backup.nix, configs/applicative.nix, and extended in 5+ system files. Hard to see what a given machine backs up.
### 7. configs/ vs modules/ distinction blurry
`configs/` has both stateless config fragments (spacetime.nix = timezone) and stateful ones (backup.nix, cloud.nix). `modules/` has proper option-declaring modules. Some configs/ files import from modules/.
## Machines Overview
| Machine | Role | Profile | Arch | Notes |
|-----------|--------------|------------------|---------|---------------------------------------|
| fatteh | Desktop | default+desktop | x86_64 | ThinkPad T480, CUDA, main daily |
| kabsa | Desktop | default+desktop | x86_64 | ThinkPad X220, constrained (2 jobs) |
| manakish | Desktop | default+desktop | x86_64 | ThinkPad X230 |
| kibbeh | Desktop | default+desktop | x86_64 | Pantheon DE, travel laptop |
| ful | Server | default+server | aarch64 | Oracle/Hetzner, nginx, web services |
| makanek | Server | default+server | x86_64 | Hetzner, gitea, nextcloud, weechat |
| zaatar | Server/Home | default+server | x86_64 | Home assistant, backup server |
| tabula | Family laptop| default | x86_64 | LXQt, user "xenos" |
| tahina | Family laptop| default | x86_64 | Pantheon, user "xenos", German |
## Remaining Improvement Ideas
1. **Extract retiolum secret boilerplate** into a function/module
2. **Break up configs/default.nix** into proper named files
3. **Extract nginx+ACME server profile**
4. **Replace niveum-* aliases** with direct niphas-* references
5. **Fix modules/retiolum.nix** NIX_PATH usage for flake purity

View File

@@ -1,18 +1,12 @@
# niveum
> I must Create a System, or be enslav'd by another Man's. —William Blake
> [nĭvĕus](https://logeion.uchicago.edu/niveus), a, um, adj. [nix], _of_ or _from snow, snowy, snow-_ (poet.)
>
> 1. Lit.: aggeribus niveis informis, Verg. G. 3, 354: aqua, _cooled with snow_, Mart. 12, 17, 6; cf. id. 14, 104 and 117: mons, _covered with snow_, Cat. 64, 240.—
>
> 2. Transf., _snow-white, snowy_ (mostly poet.): a similitudine sic: Corpore niveum candorem, aspectu igneum ardorem assequebatur, Auct. Her. 4, 33, 44: lacerti, Verg. A. 8, 387: lac, id. E. 2, 20: hanc si capite niveae agnae exorari judicas, Sen. Q. N. 2, 36: Briseis niveo colore, Hor. C. 2, 4, 3: vestis, Ov. M. 10, 432: candidior nivei folio, Galatea, ligustri, id. ib. 13, 789: dens, id. H. 18, 18: quā notam duxit niveus videri, Hor. C. 4, 2, 59: panis, Juv. 5, 70: flumen, _clear, pellucid_, Sen. Hippol. 504: undae, Mart. 7, 32, 11: tribuni, _clothed in white togas_, Calp. Ecl. 7, 29; so, Quirites, Juv. 10, 45.
## Pressestimmen
> das ist ja pure poesie —[riotbib](https://github.com/riotbib/)
> Deine Configs sind wunderschön <3 —[flxai](https://github.com/flxai/)
## To do
🦗

View File

@@ -0,0 +1,119 @@
{
pkgs,
niveumPackages,
lib,
...
}: let
darwin = lib.strings.hasSuffix "-darwin" pkgs.system;
in {
environment.systemPackages =
[
pkgs.htop
pkgs.w3m
pkgs.wget
# ARCHIVE TOOLS
pkgs.unzip
pkgs.unrar
pkgs.p7zip
pkgs.sshuttle
pkgs.zip
# MONITORS
pkgs.iftop # interface bandwidth monitor
pkgs.lsof # list open files
# SHELL
pkgs.sqlite
pkgs.fd # better find
pkgs.tree
pkgs.parallel # for parallel, since moreutils shadows task spooler
pkgs.ripgrep # better grep
pkgs.rlwrap
pkgs.progress # display progress bars for pipes
pkgs.file # determine file type
pkgs.gdu # ncurses disk usage (ncdu is broken)
pkgs.rmlint # remove duplicate files
pkgs.jq # json toolkit
pkgs.jless # less(1) for json
pkgs.fq # toolkit for yaml, xml and binaries
pkgs.bc # calculator
pkgs.pari # gp -- better calculator
pkgs.ts
niveumPackages.vimv
niveumPackages.vg
niveumPackages.fkill
niveumPackages.cyberlocker-tools
niveumPackages.untilport
niveumPackages.kpaste
# HARDWARE
pkgs.pciutils # for lspci
]
++ lib.optionals (!darwin) [
pkgs.usbutils # for lsusb
pkgs.lshw # for lshw
pkgs.iotop # I/O load monitor
pkgs.psmisc # for killall, pstree
];
security.wrappers = {
pmount = {
setuid = true;
owner = "root";
group = "root";
source = "${pkgs.pmount}/bin/pmount";
};
pumount = {
setuid = true;
owner = "root";
group = "root";
source = "${pkgs.pmount}/bin/pumount";
};
};
environment.shellAliases = let
take = pkgs.writers.writeDash "take" ''
mkdir "$1" && cd "$1"
'';
cdt = pkgs.writers.writeDash "cdt" ''
cd "$(mktemp -d)"
pwd
'';
wcd = pkgs.writers.writeDash "wcd" ''
cd "$(readlink "$(${pkgs.which}/bin/which --skip-alias "$1")" | xargs dirname)/.."
'';
where = pkgs.writers.writeDash "where" ''
readlink "$(${pkgs.which}/bin/which --skip-alias "$1")" | xargs dirname
'';
in
{
nixi = "nix repl '<nixpkgs>'";
take = "source ${take}";
wcd = "source ${wcd}";
where = "source ${where}";
# temporary files and directories
cdt = "source ${cdt}";
vit = "$EDITOR $(mktemp)";
# file safety
mv = "${pkgs.coreutils}/bin/mv --interactive";
rm = "${pkgs.coreutils}/bin/rm --interactive";
cp = "${pkgs.coreutils}/bin/cp --interactive";
# colours
cat = "${pkgs.bat}/bin/bat --theme=ansi --style=plain";
l = "${pkgs.coreutils}/bin/ls --color=auto --time-style=long-iso --almost-all";
ls = "${pkgs.coreutils}/bin/ls --color=auto --time-style=long-iso";
ll = "${pkgs.coreutils}/bin/ls --color=auto --time-style=long-iso -l";
la = "${pkgs.coreutils}/bin/ls --color=auto --time-style=long-iso --almost-all -l";
}
// (
if darwin
then {}
else {
"ß" = "${pkgs.util-linux}/bin/setsid";
ip = "${pkgs.iproute2}/bin/ip -c";
# systemd
s = "${pkgs.systemd}/bin/systemctl";
us = "${pkgs.systemd}/bin/systemctl --user";
j = "${pkgs.systemd}/bin/journalctl";
uj = "${pkgs.systemd}/bin/journalctl --user";
}
);
}

View File

@@ -2,18 +2,20 @@
pkgs,
config,
lib,
niveumPackages,
...
}:
{
}: let
inherit (import ../lib/email.nix) defaults thunderbirdProfile;
in {
age.secrets = {
email-password-ical-ephemeris = {
file = ../secrets/email-password-ical-ephemeris.age;
email-password-cock = {
file = ../secrets/email-password-cock.age;
owner = config.users.users.me.name;
group = config.users.users.me.group;
mode = "400";
};
email-password-cock = {
file = ../secrets/email-password-cock.age;
email-password-letos = {
file = ../secrets/email-password-letos.age;
owner = config.users.users.me.name;
group = config.users.users.me.group;
mode = "400";
@@ -41,15 +43,14 @@
extraConfig = {
database.path = config.home-manager.users.me.accounts.email.maildirBasePath;
new.tags = "";
user.name = pkgs.lib.niveum.email.defaults.realName;
user.name = defaults.realName;
user.primary_email = config.home-manager.users.me.accounts.email.accounts.posteo.address;
};
};
programs.mbsync = {
enable = true;
extraConfig = lib.concatStringsSep "\n\n" (
lib.mapAttrsToList (name: account: ''
extraConfig = lib.concatStringsSep "\n\n" (lib.mapAttrsToList (name: account: ''
IMAPAccount ${name}
CertificateFile /etc/ssl/certs/ca-certificates.crt
Host ${account.imap.host}
@@ -73,61 +74,53 @@
Patterns *
Remove None
SyncState *
'') config.home-manager.users.me.accounts.email.accounts
);
'')
config.home-manager.users.me.accounts.email.accounts);
};
accounts.email.accounts = {
cock =
let
mailhost = "mail.cock.li";
lib.recursiveUpdate defaults
rec {
address = "2210@cock.li";
in
lib.recursiveUpdate pkgs.lib.niveum.email.defaults {
address = address;
userName = address;
passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.email-password-cock.path}";
realName = "2210";
imap.host = mailhost;
imap.host = "mail.cock.li";
imap.port = 993;
smtp.host = mailhost;
smtp.port = 587;
smtp.host = imap.host;
smtp.port = 25;
smtp.tls.useStartTls = true;
};
ical-ephemeris =
let
address = "ical.ephemeris@web.de";
in
lib.recursiveUpdate pkgs.lib.niveum.email.defaults {
userName = address;
realName = "Kieran from iCal Ephemeris";
address = address;
passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.email-password-ical-ephemeris.path}";
imap.host = "imap.web.de";
letos =
lib.recursiveUpdate defaults
{
userName = "slfletos";
address = "letos.sprachlit@hu-berlin.de";
passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.email-password-letos.path}";
imap.host = "mailbox.cms.hu-berlin.de";
imap.port = 993;
smtp.host = "smtp.web.de";
smtp.port = 587;
smtp.host = "mailhost.cms.hu-berlin.de";
smtp.port = 25;
smtp.tls.useStartTls = true;
};
posteo =
let
mailhost = "posteo.de";
lib.recursiveUpdate defaults
rec {
address = "kieran.meinhardt@posteo.net";
in
lib.recursiveUpdate pkgs.lib.niveum.email.defaults {
address = address;
aliases = [ "kmein@posteo.de" ];
aliases = ["kmein@posteo.de"];
userName = address;
imap.host = mailhost;
imap.host = "posteo.de";
imap.port = 993;
imap.tls.enable = true;
smtp.host = mailhost;
smtp.host = imap.host;
smtp.port = 465;
smtp.tls.enable = true;
primary = true;
passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.email-password-posteo.path}";
himalaya = {
enable = true;
settings.backend = "imap";
};
aerc.extraAccounts.pgp-key-id = "9EDE82CC72A343A95266D0F444857074A3ACC8B7";
};
@@ -139,7 +132,7 @@
enable = true;
settings = {
};
profiles.${pkgs.lib.niveum.email.thunderbirdProfile} = {
profiles.${thunderbirdProfile} = {
isDefault = true;
settings = {
"mail.default_send_format" = 1;
@@ -147,8 +140,10 @@
"msgcompose.text_color" = config.lib.stylix.colors.withHashtag.base00;
"msgcompose.background_color" = config.lib.stylix.colors.withHashtag.base05;
};
userChrome = '''';
userContent = '''';
userChrome = ''
'';
userContent = ''
'';
withExternalGnupg = false;
};
};
@@ -210,7 +205,7 @@
"*" = ":filter -x Flagged<Enter>";
};
view = {
tr = ":pipe ${pkgs.trans}/bin/trans -show-original n -b -no-autocorrect<Enter>"; # https://man.sr.ht/~rjarry/aerc/integrations/translator.md
tr = ":pipe ${niveumPackages.trans}/bin/trans -show-original n -b -no-autocorrect<Enter>"; # https://man.sr.ht/~rjarry/aerc/integrations/translator.md
"/" = ":toggle-key-passthrough <Enter> /";
q = ":close<Enter>";
O = ":open<Enter>";
@@ -283,9 +278,7 @@
ui.spinner = ". , .";
general.unsafe-accounts-conf = true;
general.pgp-provider = "gpg";
viewer = {
pager = "${pkgs.less}/bin/less -R";
};
viewer = {pager = "${pkgs.less}/bin/less -R";};
compose = {
# address-book-cmd = "khard email --remove-first-line --parsable '%s'";
no-attachment-warning = "(attach|attached|attachments?|anbei|Anhang|angehängt|beigefügt)";
@@ -302,26 +295,24 @@
"message/rfc822" = "${pkgs.aerc}/libexec/aerc/filters/colorize";
"application/x-sh" = "${pkgs.bat}/bin/bat -fP -l sh";
};
openers =
let
as-pdf = pkgs.writers.writeDash "as-pdf" ''
d=$(mktemp -p "$XDG_RUNTIME_DIR" -d)
trap clean EXIT
clean() {
rm -rf "$d"
}
${pkgs.libreoffice}/bin/libreoffice --headless --convert-to pdf "$1" --outdir "$d"
${pkgs.zathura}/bin/zathura "$d"/*.pdf
'';
in
{
"image/*" = "${pkgs.nsxiv}/bin/nsxiv";
"application/pdf" = "${pkgs.zathura}/bin/zathura";
"application/vnd.openxmlformats-officedocument.wordprocessingml.document" = toString as-pdf;
"application/vnd.oasis.opendocument.text" = toString as-pdf;
"video/*" = "${pkgs.mpv}/bin/mpv";
"audio/*" = "${pkgs.mpv}/bin/mpv";
};
openers = let
as-pdf = pkgs.writers.writeDash "as-pdf" ''
d=$(mktemp -d)
trap clean EXIT
clean() {
rm -rf "$d"
}
${pkgs.libreoffice}/bin/libreoffice --headless --convert-to pdf "$1" --outdir "$d"
${pkgs.zathura}/bin/zathura "$d"/*.pdf
'';
in {
"image/*" = "${pkgs.nsxiv}/bin/nsxiv";
"application/pdf" = "${pkgs.zathura}/bin/zathura";
"application/vnd.openxmlformats-officedocument.wordprocessingml.document" = toString as-pdf;
"application/vnd.oasis.opendocument.text" = toString as-pdf;
"video/*" = "${pkgs.mpv}/bin/mpv";
"audio/*" = "${pkgs.mpv}/bin/mpv";
};
};
templates = {

View File

@@ -1,7 +1,33 @@
{
pkgs,
lib,
...
}: let
in {
environment.variables.TERMINAL = "alacritty";
home-manager.users.me = {
programs.alacritty = {
enable = true;
settings = {
keyboard.bindings = [
{
key = "Plus";
mods = "Control";
action = "IncreaseFontSize";
}
{
key = "Minus";
mods = "Control";
action = "DecreaseFontSize";
}
{
key = "Key0";
mods = "Control";
action = "ResetFontSize";
}
];
};
};
};
}

View File

@@ -1,5 +1,5 @@
{
programs.adb.enable = true;
users.users.me.extraGroups = [ "adbusers" ];
users.users.me.extraGroups = ["adbusers"];
}

View File

@@ -1,58 +0,0 @@
{
config,
pkgs,
lib,
...
}:
{
users.users.applicative = {
name = "asg";
description = "Applicative Systems";
hashedPasswordFile = config.age.secrets.kfm-password.path;
home = "/home/applicative";
uid = 1001;
isNormalUser = true;
extraGroups = [
"pipewire"
"audio"
];
};
nixpkgs.overlays = [
(final: prev: {
niphas-wallpaper = prev.callPackage ../packages/applicative-wallpaper.nix {
inherit (config.lib.stylix) colors;
};
})
];
services.getty.autologinOnce = lib.mkForce false;
# to run nspawn in nix sandbox
nix.settings = {
auto-allocate-uids = true;
system-features = [ "uid-range" ];
experimental-features = [
"auto-allocate-uids"
"cgroups"
];
trusted-users = [ config.users.users.applicative.name ];
};
services.restic.backups.niveum = {
extraBackupArgs = [
"--exclude=${config.users.users.applicative.home}/src/nixpkgs/.git"
];
paths = [
config.users.users.applicative.home
];
};
security.sudo.extraRules = [
{
# still required for systemd-nspawn
users = [ config.users.users.applicative.name ];
commands = [ "ALL" ];
}
];
}

View File

@@ -1,13 +1,13 @@
{
pkgs,
config,
lib,
...
}:
{
}: let
inherit (import ../lib) restic;
in {
services.restic.backups.niveum = {
initialize = true;
repository = pkgs.lib.niveum.restic.repository;
inherit (restic) repository;
timerConfig = {
OnCalendar = "8:00";
RandomizedDelaySec = "1h";
@@ -38,15 +38,15 @@
environment.systemPackages = [
(pkgs.writers.writeDashBin "restic-niveum" ''
${pkgs.restic}/bin/restic -r ${pkgs.lib.niveum.restic.repository} -p ${config.age.secrets.restic.path} "$@"
${pkgs.restic}/bin/restic -r ${restic.repository} -p ${config.age.secrets.restic.path} "$@"
'')
(pkgs.writers.writeDashBin "restic-mount" ''
mountdir=$(mktemp -p "$XDG_RUNTIME_DIR" -d "restic-mount-XXXXXXX")
mountdir=$(mktemp -d)
trap clean EXIT
clean() {
rm -r "$mountdir"
}
${pkgs.restic}/bin/restic -r ${pkgs.lib.niveum.restic.repository} -p ${config.age.secrets.restic.path} mount "$mountdir"
${pkgs.restic}/bin/restic -r ${restic.repository} -p ${config.age.secrets.restic.path} mount "$mountdir"
'')
];
}

10
configs/bash.nix Normal file
View File

@@ -0,0 +1,10 @@
{pkgs, ...}: {
programs.bash = {
promptInit = ''
PS1="$(${pkgs.ncurses}/bin/tput bold)\w \$([[ \$? == 0 ]] && echo \"\[\033[1;32m\]\" || echo \"\[\033[1;31m\]\")\$$(${pkgs.ncurses}/bin/tput sgr0) "'';
interactiveShellInit = ''
set -o vi
'';
enableCompletion = true;
};
}

View File

@@ -1,5 +1,4 @@
{ pkgs, ... }:
{
{pkgs, ...}: {
hardware.bluetooth = {
enable = true;
settings.general = {

View File

@@ -1,19 +1,28 @@
{
config,
pkgs,
lib,
config,
...
}:
{
}: let
autorenkalender-package = pkgs.fetchFromGitHub {
owner = "kmein";
repo = "autorenkalender";
rev = "cf49a7b057301332d980eb47042a626add93db66";
sha256 = "1pa7sjg33vdnjianrqldv445jdzzv3mn231ljk1j58hs0cd505gs";
};
autorenkalender =
pkgs.python3Packages.callPackage autorenkalender-package {};
in {
niveum.bots.autorenkalender = {
enable = true;
time = "07:00";
telegram = {
enable = true;
tokenFile = config.age.secrets.telegram-token-kmein.path;
chatIds = [ "@autorenkalender" ];
chatIds = ["@autorenkalender"];
parseMode = "Markdown";
};
command = "${pkgs.autorenkalender}/bin/autorenkalender";
command = "${autorenkalender}/bin/autorenkalender";
};
niveum.passport.services = [

View File

@@ -3,69 +3,64 @@
lib,
config,
...
}:
{
}: {
niveum.bots.celan = {
enable = true;
time = "08:00";
telegram = {
enable = true;
tokenFile = config.age.secrets.telegram-token-kmein.path;
chatIds = [ "@PaulCelan" ];
chatIds = ["@PaulCelan"];
};
mastodon = {
enable = true;
tokenFile = config.age.secrets.mastodon-token-celan.path;
language = "de";
};
command = toString (
pkgs.writers.writePython3 "random-celan.py" { libraries = [ pkgs.python3Packages.lxml ]; } ''
from lxml import etree
import random
command = toString (pkgs.writers.writePython3 "random-celan.py" { libraries = [pkgs.python3Packages.lxml]; } ''
from lxml import etree
import random
def xml_text(elements):
return "".join("".join(t.itertext()) for t in elements).strip()
def xml_text(elements):
return "".join("".join(t.itertext()) for t in elements).strip()
tree = etree.parse('${
pkgs.fetchurl {
url = "http://c.krebsco.de/celan.tei.xml";
hash = "sha256-HgNmJYfhuwyfm+FcNtnnYWpJpIIU1ElHLeLiIFjF9mE=";
}
}')
root = tree.getroot()
tree = etree.parse('${pkgs.fetchurl {
url = "http://c.krebsco.de/celan.tei.xml";
hash = "sha256-HgNmJYfhuwyfm+FcNtnnYWpJpIIU1ElHLeLiIFjF9mE=";
}}')
root = tree.getroot()
tei = {"tei": "http://www.tei-c.org/ns/1.0"}
tei = {"tei": "http://www.tei-c.org/ns/1.0"}
poems = root.xpath(".//tei:lg[@type='poem']", namespaces=tei)
poems = root.xpath(".//tei:lg[@type='poem']", namespaces=tei)
poem = random.choice(poems)
poem = random.choice(poems)
for stanza in poem.xpath("./tei:lg[@type='stanza']", namespaces=tei):
for line in stanza.xpath('./tei:l', namespaces=tei):
if line.text:
print(line.text.strip())
print()
for stanza in poem.xpath("./tei:lg[@type='stanza']", namespaces=tei):
for line in stanza.xpath('./tei:l', namespaces=tei):
if line.text:
print(line.text.strip())
print()
current_element = poem
while current_element is not None:
if current_element.tag == "{http://www.tei-c.org/ns/1.0}text":
text_element = current_element
current_element = poem
while current_element is not None:
if current_element.tag == "{http://www.tei-c.org/ns/1.0}text":
text_element = current_element
title = xml_text(text_element.xpath("./tei:front/tei:docTitle",
namespaces=tei))
print(f"Aus: #{title.replace(" ", "_")}", end=" ")
title = xml_text(text_element.xpath("./tei:front/tei:docTitle",
namespaces=tei))
print(f"Aus: #{title.replace(" ", "_")}", end=" ")
if date := xml_text(text_element.xpath("./tei:front/tei:docDate",
namespaces=tei)):
print(f"({date})")
break
current_element = current_element.getparent()
if date := xml_text(text_element.xpath("./tei:front/tei:docDate",
namespaces=tei)):
print(f"({date})")
break
current_element = current_element.getparent()
print("\n\n#PaulCelan #Celan #Lyrik #poetry")
''
);
print("\n\n#PaulCelan #Celan #Lyrik #poetry")
'');
};
age.secrets = {

View File

@@ -1,13 +1,15 @@
{
config,
pkgs,
lib,
inputs,
...
}:
let
}: let
telebots = inputs.telebots.defaultPackage.x86_64-linux;
reverseDirectory = "/run/telegram-reverse";
proverbDirectory = "/run/telegram-proverb";
in
{
inherit (import ../../lib) tmpfilesConfig;
in {
imports = [
./logotheca.nix
./transits.nix
@@ -15,30 +17,18 @@ in
./hesychius.nix
./smyth.nix
./nachtischsatan.nix
# ./tlg-wotd.nix TODO reenable
./tlg-wotd.nix
./celan.nix
./nietzsche.nix
];
age.secrets = {
telegram-token-kmein.file = ../../secrets/telegram-token-kmein.age;
};
systemd.tmpfiles.rules =
map
(
path:
pkgs.lib.niveum.tmpfilesConfig {
type = "d";
mode = "0750";
age = "1h";
inherit path;
}
)
[
reverseDirectory
proverbDirectory
];
systemd.tmpfiles.rules = map (path:
tmpfilesConfig {
type = "d";
mode = "0750";
age = "1h";
inherit path;
}) [reverseDirectory proverbDirectory];
niveum.passport.services = [
{
@@ -66,12 +56,12 @@ in
};
systemd.services.telegram-reverse = {
wantedBy = [ "multi-user.target" ];
wantedBy = ["multi-user.target"];
description = "Telegram reverse bot";
path = [ pkgs.ffmpeg ];
path = [pkgs.ffmpeg];
enable = true;
script = ''
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${pkgs.telebots}/bin/telegram-reverse
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${telebots}/bin/telegram-reverse
'';
serviceConfig.Restart = "always";
serviceConfig.WorkingDirectory = reverseDirectory;
@@ -79,33 +69,33 @@ in
};
systemd.services.telegram-streaming-link = {
wantedBy = [ "multi-user.target" ];
wantedBy = ["multi-user.target"];
description = "Telegram bot converting YouTube Music <-> Spotify";
enable = true;
script = ''
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${pkgs.telebots}/bin/telegram-streaming-link
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${telebots}/bin/telegram-streaming-link
'';
serviceConfig.Restart = "always";
serviceConfig.LoadCredential = "token:${config.age.secrets.telegram-token-streaming-link.path}";
};
systemd.services.telegram-betacode = {
wantedBy = [ "multi-user.target" ];
wantedBy = ["multi-user.target"];
description = "Telegram beta code bot";
enable = true;
script = ''
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${pkgs.telebots}/bin/telegram-betacode
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${telebots}/bin/telegram-betacode
'';
serviceConfig.Restart = "always";
serviceConfig.LoadCredential = "token:${config.age.secrets.telegram-token-betacode.path}";
};
systemd.services.telegram-proverb = {
wantedBy = [ "multi-user.target" ];
wantedBy = ["multi-user.target"];
description = "Telegram proverb bot";
enable = true;
script = ''
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${pkgs.telebots}/bin/telegram-proverb
TELEGRAM_BOT_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/token")" ${telebots}/bin/telegram-proverb
'';
serviceConfig.Restart = "always";
serviceConfig.WorkingDirectory = proverbDirectory;

View File

@@ -1,9 +1,12 @@
{
pkgs,
config,
inputs,
lib,
...
}:
{
}: let
hesychius = inputs.scripts.outPath + "/hesychius/hesychius.txt";
in {
niveum.bots.hesychius = {
enable = true;
time = "08:00";
@@ -15,9 +18,9 @@
telegram = {
enable = true;
tokenFile = config.age.secrets.telegram-token-kmein.path;
chatIds = [ "@HesychiosAlexandreus" ];
chatIds = ["@HesychiosAlexandreus"];
};
command = "${pkgs.coreutils}/bin/shuf -n1 ${pkgs.hesychius}";
command = "${pkgs.coreutils}/bin/shuf -n1 ${hesychius}";
};
systemd.timers.bot-hesychius.timerConfig.RandomizedDelaySec = "10h";

View File

@@ -1,16 +1,17 @@
{
pkgs,
config,
lib,
niveumPackages,
...
}:
{
}: {
niveum.bots.logotheca = {
enable = true;
time = "08/6:00";
telegram = {
enable = true;
tokenFile = config.age.secrets.telegram-token-kmein.path;
chatIds = [ "-1001760262519" ];
chatIds = ["-1001760262519"];
parseMode = "Markdown";
};
matrix = {
@@ -21,7 +22,7 @@
"!zlwCuPiCNMSxDviFzA:4d2.org"
];
};
command = "${pkgs.literature-quote}/bin/literature-quote";
command = "${niveumPackages.literature-quote}/bin/literature-quote";
};
age.secrets = {

View File

@@ -3,36 +3,31 @@
config,
lib,
...
}:
let
nachtischsatan-bot =
{ tokenFile }:
pkgs.writers.writePython3 "nachtischsatan-bot"
{
libraries = [ pkgs.python3Packages.python-telegram-bot ];
}
''
from telegram.ext import Application, ContextTypes, MessageHandler, filters
from telegram import Update
import random
import time
}: let
nachtischsatan-bot = {tokenFile}:
pkgs.writers.writePython3 "nachtischsatan-bot" {
libraries = [pkgs.python3Packages.python-telegram-bot];
} ''
from telegram.ext import Application, ContextTypes, MessageHandler, filters
from telegram import Update
import random
import time
async def flubber(update: Update, context: ContextTypes.DEFAULT_TYPE):
time.sleep(random.randrange(4000) / 1000)
await update.message.reply_text("*flubberflubber*")
async def flubber(update: Update, context: ContextTypes.DEFAULT_TYPE):
time.sleep(random.randrange(4000) / 1000)
await update.message.reply_text("*flubberflubber*")
with open('${tokenFile}', 'r') as tokenFile:
token = tokenFile.read().strip()
application = Application.builder().token(token).build()
application.add_handler(MessageHandler(filters.ALL, flubber))
application.run_polling()
'';
in
{
with open('${tokenFile}', 'r') as tokenFile:
token = tokenFile.read().strip()
application = Application.builder().token(token).build()
application.add_handler(MessageHandler(filters.ALL, flubber))
application.run_polling()
'';
in {
systemd.services.telegram-nachtischsatan = {
wantedBy = [ "multi-user.target" ];
wantedBy = ["multi-user.target"];
description = "*flubberflubber*";
enable = true;
script = toString (nachtischsatan-bot {

View File

@@ -1,9 +1,9 @@
{
config,
pkgs,
niveumPackages,
...
}:
{
}: {
niveum.bots.nietzsche = {
enable = true;
time = "08:00";
@@ -12,17 +12,15 @@
tokenFile = config.age.secrets.mastodon-token-nietzsche.path;
language = "de";
};
command = toString (
pkgs.writers.writeBash "random-nietzsche" ''
set -efu
random_number=$(( ($RANDOM % 10) + 1 ))
if [ "$random_number" -eq 1 ]; then
${pkgs.random-zeno}/bin/random-zeno "/Literatur/M/Nietzsche,+Friedrich"
else
${pkgs.random-zeno}/bin/random-zeno "/Philosophie/M/Nietzsche,+Friedrich"
fi
''
);
command = toString (pkgs.writers.writeBash "random-nietzsche" ''
set -efu
random_number=$(( ($RANDOM % 10) + 1 ))
if [ "$random_number" -eq 1 ]; then
${niveumPackages.random-zeno}/bin/random-zeno "/Literatur/M/Nietzsche,+Friedrich"
else
${niveumPackages.random-zeno}/bin/random-zeno "/Philosophie/M/Nietzsche,+Friedrich"
fi
'');
};
systemd.timers.bot-nietzsche.timerConfig.RandomizedDelaySec = "10h";

View File

@@ -3,8 +3,7 @@
pkgs,
lib,
...
}:
{
}: {
niveum.bots.smyth = {
enable = true;
time = "08:00";
@@ -16,44 +15,26 @@
telegram = {
enable = true;
tokenFile = config.age.secrets.telegram-token-kmein.path;
chatIds = [ "@HerbertWeirSmyth" ];
chatIds = ["@HerbertWeirSmyth"];
};
command = toString (
pkgs.writers.writeDash "random-smyth" ''
set -efu
command = toString (pkgs.writers.writeDash "random-smyth" ''
set -efu
good_curl() {
${pkgs.curl}/bin/curl "$@" \
--compressed \
-H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \
-H 'Accept-Language: en-US,en;q=0.5' \
-H 'DNT: 1' \
-H 'Connection: keep-alive' \
-H 'Upgrade-Insecure-Requests: 1' \
-H 'Sec-Fetch-Dest: document' \
-H 'Sec-Fetch-Mode: navigate' \
-H 'Sec-Fetch-Site: cross-site' \
-H 'Priority: u=0, i' \
-H 'Pragma: no-cache' \
-H 'Cache-Control: no-cache'
}
RANDOM_SECTION=$(
${pkgs.curl}/bin/curl -sSL http://www.perseus.tufts.edu/hopper/xmltoc?doc=Perseus%3Atext%3A1999.04.0007%3Asmythp%3D1 \
| ${pkgs.gnugrep}/bin/grep -o 'ref="[^"]*"' \
| ${pkgs.coreutils}/bin/shuf -n1 \
| ${pkgs.gnused}/bin/sed 's/^ref="//;s/"$//'
)
RANDOM_SECTION=$(
good_curl -sSL http://www.perseus.tufts.edu/hopper/xmltoc?doc=Perseus%3Atext%3A1999.04.0007%3Asmythp%3D1 \
| ${pkgs.gnugrep}/bin/grep -o 'ref="[^"]*"' \
| ${pkgs.coreutils}/bin/shuf -n1 \
| ${pkgs.gnused}/bin/sed 's/^ref="//;s/"$//'
)
url="http://www.perseus.tufts.edu/hopper/text?doc=$RANDOM_SECTION"
${pkgs.curl}/bin/curl -sSL "$url"\
| ${pkgs.htmlq}/bin/htmlq '#text_main' \
| ${pkgs.gnused}/bin/sed 's/<\/\?hr>//g' \
| ${pkgs.pandoc}/bin/pandoc -f html -t plain --wrap=none
url="http://www.perseus.tufts.edu/hopper/text?doc=$RANDOM_SECTION"
good_curl -sSL "$url"\
| ${pkgs.htmlq}/bin/htmlq '#text_main' \
| ${pkgs.gnused}/bin/sed 's/<\/\?hr>//g' \
| ${pkgs.pandoc}/bin/pandoc -f html -t plain --wrap=none
printf '\n%s\n\n#AncientGreek' "$url"
''
);
printf '\n%s\n\n#AncientGreek' "$url"
'');
};
systemd.timers.bot-smyth.timerConfig.RandomizedDelaySec = "10h";

View File

@@ -1,154 +1,140 @@
{
pkgs,
lib,
config,
niveumPackages,
...
}:
let
}: let
mastodonEndpoint = "https://social.krebsco.de";
in
{
in {
systemd.services.bot-tlg-wotd = {
# TODO reenable
# once https://github.com/NixOS/nixpkgs/pull/462893 is in stable NixOS
enable = true;
wants = [ "network-online.target" ];
wants = ["network-online.target"];
startAt = "9:30";
path = [
pkgs.jq
pkgs.curl
pkgs.recode
pkgs.deno
pkgs.imagemagick
pkgs.gawk
pkgs.gnugrep
pkgs.coreutils
];
path = [ pkgs.jq pkgs.curl pkgs.recode pkgs.deno pkgs.imagemagick pkgs.gawk pkgs.gnugrep pkgs.coreutils ];
environment = {
NPM_CONFIG_CACHE = "/tmp";
CLTK_DATA = "/tmp";
};
script = ''
set -efux
set -efux
chat_id=@tlgwotd
chat_id=@tlgwotd
export TELEGRAM_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/telegram-token")"
export MASTODON_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/mastodon-token")"
export TELEGRAM_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/telegram-token")"
export MASTODON_TOKEN="$(cat "$CREDENTIALS_DIRECTORY/mastodon-token")"
json_data=$(curl -sSL http://stephanus.tlg.uci.edu/Iris/Wotd | recode html..utf8)
json_data=$(curl -sSL http://stephanus.tlg.uci.edu/Iris/Wotd | recode html..utf8)
word=$(echo "$json_data" | jq -r '.word')
compact_word=$(echo "$word" | sed 's/,.*$//')
definition=$(echo "$json_data" | jq -r '.definition | sub("<.*>"; "") | rtrimstr(" ")')
first_occurrence=$(echo "$json_data" | jq -r '.firstOccurrence')
total_occurrences=$(echo "$json_data" | jq -r '.totalOccurrences')
telegram_caption="*$word* $definition
word=$(echo "$json_data" | jq -r '.word')
compact_word=$(echo "$word" | sed 's/,.*$//')
definition=$(echo "$json_data" | jq -r '.definition | sub("<.*>"; "") | rtrimstr(" ")')
first_occurrence=$(echo "$json_data" | jq -r '.firstOccurrence')
total_occurrences=$(echo "$json_data" | jq -r '.totalOccurrences')
telegram_caption="*$word* $definition
First occurrence (century): $first_occurrence
Number of occurrences (in all Ancient Greek texts): $total_occurrences"
mastodon_caption="$word $definition
First occurrence (century): $first_occurrence
Number of occurrences (in all Ancient Greek texts): $total_occurrences"
mastodon_caption="$word $definition
First occurrence (century): $first_occurrence
Number of occurrences (in all Ancient Greek texts): $total_occurrences"
First occurrence (century): $first_occurrence
Number of occurrences (in all Ancient Greek texts): $total_occurrences"
#ancientgreek #classics #wotd #wordoftheday
#ancientgreek #classics #wotd #wordoftheday
transliteration=$(${
pkgs.writers.writePython3 "translit.py"
{
libraries = py: [ py.cltk ];
}
''
import sys
from cltk.phonology.grc.transcription import Transcriber
transliteration=$(${pkgs.writers.makePythonWriter pkgs.python311 pkgs.python311Packages pkgs.python3Packages "translit.py" {
# revert to pkgs.writers.writePython3 once https://github.com/NixOS/nixpkgs/pull/353367 is merged
libraries = [ pkgs.python3Packages.cltk ];
} ''
import sys
from cltk.phonology.grc.transcription import Transcriber
probert = Transcriber("Attic", "Probert")
text = " ".join(sys.argv[1:])
ipa = probert.transcribe(text)
probert = Transcriber("Attic", "Probert")
text = " ".join(sys.argv[1:])
ipa = probert.transcribe(text)
print(ipa)
''
} "$compact_word")
print(ipa)
''} "$compact_word")
photo_path=/tmp/output.png
photo_path=/tmp/output.png
hex_to_rgb() {
hex="$1"
r=$(printf "%d" "0x$(echo "$hex" | cut -c2-3)")
g=$(printf "%d" "0x$(echo "$hex" | cut -c4-5)")
b=$(printf "%d" "0x$(echo "$hex" | cut -c6-7)")
echo "$r $g $b"
}
hex_to_rgb() {
hex="$1"
r=$(printf "%d" "0x$(echo "$hex" | cut -c2-3)")
g=$(printf "%d" "0x$(echo "$hex" | cut -c4-5)")
b=$(printf "%d" "0x$(echo "$hex" | cut -c6-7)")
echo "$r $g $b"
}
calculate_luminance() {
r="$1"
g="$2"
b="$3"
calculate_luminance() {
r="$1"
g="$2"
b="$3"
r_l=$(echo "$r" | awk '{print ($1 / 255 <= 0.03928) ? $1 / 255 / 12.92 : (($1 / 255 + 0.055) / 1.055)^2.4}')
g_l=$(echo "$g" | awk '{print ($1 / 255 <= 0.03928) ? $1 / 255 / 12.92 : (($1 / 255 + 0.055) / 1.055)^2.4}')
b_l=$(echo "$b" | awk '{print ($1 / 255 <= 0.03928) ? $1 / 255 / 12.92 : (($1 / 255 + 0.055) / 1.055)^2.4}')
r_l=$(echo "$r" | awk '{print ($1 / 255 <= 0.03928) ? $1 / 255 / 12.92 : (($1 / 255 + 0.055) / 1.055)^2.4}')
g_l=$(echo "$g" | awk '{print ($1 / 255 <= 0.03928) ? $1 / 255 / 12.92 : (($1 / 255 + 0.055) / 1.055)^2.4}')
b_l=$(echo "$b" | awk '{print ($1 / 255 <= 0.03928) ? $1 / 255 / 12.92 : (($1 / 255 + 0.055) / 1.055)^2.4}')
echo "$r_l $g_l $b_l" | awk '{print 0.2126*$1 + 0.7152*$2 + 0.0722*$3}'
}
echo "$r_l $g_l $b_l" | awk '{print 0.2126*$1 + 0.7152*$2 + 0.0722*$3}'
}
hex_color="#$(echo "$compact_word" | md5sum | cut -c 1-6)"
if echo "$hex_color" | grep -qE '^#[0-9A-Fa-f]{6}$'; then
set -- $(hex_to_rgb "$hex_color")
r="$1"
g="$2"
b="$3"
fi
hex_color="#$(echo "$compact_word" | md5sum | cut -c 1-6)"
if echo "$hex_color" | grep -qE '^#[0-9A-Fa-f]{6}$'; then
set -- $(hex_to_rgb "$hex_color")
r="$1"
g="$2"
b="$3"
fi
luminance=$(calculate_luminance "$r" "$g" "$b")
luminance=$(calculate_luminance "$r" "$g" "$b")
threshold="0.1"
echo "$r $g $b"
if [ "$(echo "$luminance" | awk -v threshold="$threshold" '{print ($1 > threshold)}')" -eq 1 ]; then
color1="black"
color2="#333"
else
color1="white"
color2=lightgrey
fi
threshold="0.1"
echo "$r $g $b"
if [ "$(echo "$luminance" | awk -v threshold="$threshold" '{print ($1 > threshold)}')" -eq 1 ]; then
color1="black"
color2="#333"
else
color1="white"
color2=lightgrey
fi
magick -size 1400x846 \
xc:"$hex_color" \
-font "${pkgs.gentium}/share/fonts/truetype/GentiumBookPlus-Bold.ttf" \
-fill "$color1" \
-pointsize 150 -gravity west \
-annotate +100-160 "$compact_word" \
-font "${pkgs.gentium}/share/fonts/truetype/GentiumBookPlus-Regular.ttf" \
-fill "$color2" \
-pointsize 60 -gravity west \
-annotate +100+00 "$transliteration" \
-fill "$color1" \
-annotate +100+120 "$definition" \
-fill "$color2" \
-pointsize 40 -gravity southwest \
-annotate +100+60 "attested $total_occurrences times" \
-pointsize 40 -gravity southeast \
-annotate +100+60 "$(date -I)" \
"$photo_path"
magick -size 1400x846 \
xc:"$hex_color" \
-font "${pkgs.gentium}/share/fonts/truetype/GentiumBookPlus-Bold.ttf" \
-fill "$color1" \
-pointsize 150 -gravity west \
-annotate +100-160 "$compact_word" \
-font "${pkgs.gentium}/share/fonts/truetype/GentiumBookPlus-Regular.ttf" \
-fill "$color2" \
-pointsize 60 -gravity west \
-annotate +100+00 "$transliteration" \
-fill "$color1" \
-annotate +100+120 "$definition" \
-fill "$color2" \
-pointsize 40 -gravity southwest \
-annotate +100+60 "attested $total_occurrences times" \
-pointsize 40 -gravity southeast \
-annotate +100+60 "$(date -I)" \
"$photo_path"
curl -X POST "https://api.telegram.org/bot$TELEGRAM_TOKEN/sendPhoto" \
-F "chat_id=\"$chat_id\"" \
-F "photo=@$photo_path" \
-F parse_mode=Markdown \
-F caption="$telegram_caption"
curl -X POST "https://api.telegram.org/bot$TELEGRAM_TOKEN/sendPhoto" \
-F "chat_id=\"$chat_id\"" \
-F "photo=@$photo_path" \
-F parse_mode=Markdown \
-F caption="$telegram_caption"
mastodon_upload_response=$(curl -X POST "${mastodonEndpoint}/api/v2/media" \
-H "Authorization: Bearer $MASTODON_TOKEN" \
-F "file=@$photo_path" \
-F "description=$word $definition")
mastodon_image_id=$(echo $mastodon_upload_response | jq -r .id)
curl -X POST "${mastodonEndpoint}/api/v1/statuses" \
-H "Authorization: Bearer $MASTODON_TOKEN" \
-d "status=$mastodon_caption" \
-d "visibility=public" \
-d "media_ids[]=$mastodon_image_id"
mastodon_upload_response=$(curl -X POST "${mastodonEndpoint}/api/v2/media" \
-H "Authorization: Bearer $MASTODON_TOKEN" \
-F "file=@$photo_path" \
-F "description=$word $definition")
mastodon_image_id=$(echo $mastodon_upload_response | jq -r .id)
curl -X POST "${mastodonEndpoint}/api/v1/statuses" \
-H "Authorization: Bearer $MASTODON_TOKEN" \
-d "status=$mastodon_caption" \
-d "visibility=public" \
-d "media_ids[]=$mastodon_image_id"
'';
serviceConfig = {
Type = "oneshot";
@@ -163,6 +149,7 @@ in
};
age.secrets = {
telegram-token-kmein.file = ../../secrets/telegram-token-kmein.age;
mastodon-token-tlgwotd.file = ../../secrets/mastodon-token-tlgwotd.age;
};

View File

@@ -3,8 +3,7 @@
pkgs,
lib,
...
}:
let
}: let
toSymbols = pkgs.writers.writeDash "to-symbols" ''
${pkgs.gnused}/bin/sed '
s/\bTri\b//;
@@ -41,8 +40,7 @@ let
s/^\s*//
'
'';
in
{
in {
niveum.bots.transits = {
enable = true;
time = "*:0/1";
@@ -53,21 +51,19 @@ in
telegram = {
enable = true;
tokenFile = config.age.secrets.telegram-token-kmein.path;
chatIds = [ "-1001796440545" ];
chatIds = ["-1001796440545"];
};
command = toString (
pkgs.writers.writeDash "common-transits" ''
set -efu
command = toString (pkgs.writers.writeDash "common-transits" ''
set -efu
now=$(${pkgs.coreutils}/bin/date +%_H:%M | ${pkgs.gnused}/bin/sed 's/^\s*//')
date=$(${pkgs.coreutils}/bin/date +'%m %d %Y')
(
cd ${pkgs.astrolog}/bin
# ./astrolog -Yt -Yd -q 10 22 1999 6:32 -zN Kassel -td $date -R Uranus Neptune Pluto "North Node"
./astrolog -qd $date -zN Berlin -Yt -Yd -d -R Uranus Neptune Pluto "North Node" -A 2
) | ${toSymbols} | ${pkgs.coreutils}/bin/sort -n | ${pkgs.gnugrep}/bin/grep "^$now" || :
''
);
now=$(${pkgs.coreutils}/bin/date +%_H:%M | ${pkgs.gnused}/bin/sed 's/^\s*//')
date=$(${pkgs.coreutils}/bin/date +'%m %d %Y')
(
cd ${pkgs.astrolog}/bin
# ./astrolog -Yt -Yd -q 10 22 1999 6:32 -zN Kassel -td $date -R Uranus Neptune Pluto "North Node"
./astrolog -qd $date -zN Berlin -Yt -Yd -d -R Uranus Neptune Pluto "North Node" -A 2
) | ${toSymbols} | ${pkgs.coreutils}/bin/sort -n | ${pkgs.gnugrep}/bin/grep "^$now" || :
'');
};
age.secrets = {

View File

@@ -1,12 +1,12 @@
{
config,
pkgs,
niveumPackages,
...
}:
{
}: {
environment.systemPackages = [
pkgs.cro
pkgs.tor-browser
niveumPackages.cro
pkgs.tor-browser-bundle-bin
pkgs.firefox
pkgs.brave
];
@@ -14,79 +14,73 @@
home-manager.users.me = {
programs.firefox = {
enable = true;
profiles =
let
defaultSettings = {
"beacon.enabled" = false;
"browser.bookmarks.showMobileBookmarks" = true;
"browser.newtab.preload" = false;
"browser.search.isUS" = false;
"browser.search.region" = "DE";
"browser.send_pings" = false;
"browser.shell.checkDefaultBrowser" = false;
"browser.startup.homepage" = "chrome://browser/content/blanktab.html";
"browser.uidensity" = 1;
"browser.urlbar.placeholderName" = "Search";
"datareporting.healthreport.service.enabled" = false;
"datareporting.healthreport.uploadEnabled" = false;
"datareporting.policy.dataSubmissionEnabled" = false;
"datareporting.sessions.current.clean" = true;
"distribution.searchplugins.defaultLocale" = "de-DE";
"general.smoothScroll" = true;
"identity.fxaccounts.account.device.name" = config.networking.hostName;
"network.cookie.cookieBehavior" = 1;
"privacy.donottrackheader.enabled" = true;
"privacy.trackingprotection.enabled" = true;
"privacy.trackingprotection.pbmode.enabled" = true;
"privacy.trackingprotection.socialtracking.enabled" = true;
"services.sync.declinedEngines" = "passwords";
"services.sync.engine.passwords" = false;
"signon.autofillForms" = false;
"signon.rememberSignons" = false;
"toolkit.legacyUserProfileCustomizations.stylesheets" = true;
"toolkit.telemetry.archive.enabled" = false;
"toolkit.telemetry.bhrPing.enabled" = false;
"toolkit.telemetry.cachedClientID" = "";
"toolkit.telemetry.enabled" = false;
"toolkit.telemetry.firstShutdownPing.enabled" = false;
"toolkit.telemetry.hybridContent.enabled" = false;
"toolkit.telemetry.newProfilePing.enabled" = false;
"toolkit.telemetry.prompted" = 2;
"toolkit.telemetry.rejected" = true;
"toolkit.telemetry.server" = "";
"toolkit.telemetry.shutdownPingSender.enabled" = false;
"toolkit.telemetry.unified" = false;
"toolkit.telemetry.unifiedIsOptIn" = false;
"toolkit.telemetry.updatePing.enabled" = false;
"ui.prefersReducedMotion" = 1;
};
in
{
default = {
id = 0;
isDefault = true;
settings = defaultSettings;
# extensions = with pkgs.nur.repos.rycee.firefox-addons; [
# ublock-origin
# darkreader
# sponsorblock
# consent-o-matic
# i-dont-care-about-cookies
# # auto-tab-discard TODO what is this
# ];
userChrome = ''
#TabsToolbar {
visibility: collapse !important;
}
'';
};
profiles = let
defaultSettings = {
"beacon.enabled" = false;
"browser.bookmarks.showMobileBookmarks" = true;
"browser.newtab.preload" = false;
"browser.search.isUS" = false;
"browser.search.region" = "DE";
"browser.send_pings" = false;
"browser.shell.checkDefaultBrowser" = false;
"browser.startup.homepage" = "chrome://browser/content/blanktab.html";
"browser.uidensity" = 1;
"browser.urlbar.placeholderName" = "Search";
"datareporting.healthreport.service.enabled" = false;
"datareporting.healthreport.uploadEnabled" = false;
"datareporting.policy.dataSubmissionEnabled" = false;
"datareporting.sessions.current.clean" = true;
"distribution.searchplugins.defaultLocale" = "de-DE";
"general.smoothScroll" = true;
"identity.fxaccounts.account.device.name" = config.networking.hostName;
"network.cookie.cookieBehavior" = 1;
"privacy.donottrackheader.enabled" = true;
"privacy.trackingprotection.enabled" = true;
"privacy.trackingprotection.pbmode.enabled" = true;
"privacy.trackingprotection.socialtracking.enabled" = true;
"services.sync.declinedEngines" = "passwords";
"services.sync.engine.passwords" = false;
"signon.autofillForms" = false;
"signon.rememberSignons" = false;
"toolkit.legacyUserProfileCustomizations.stylesheets" = true;
"toolkit.telemetry.archive.enabled" = false;
"toolkit.telemetry.bhrPing.enabled" = false;
"toolkit.telemetry.cachedClientID" = "";
"toolkit.telemetry.enabled" = false;
"toolkit.telemetry.firstShutdownPing.enabled" = false;
"toolkit.telemetry.hybridContent.enabled" = false;
"toolkit.telemetry.newProfilePing.enabled" = false;
"toolkit.telemetry.prompted" = 2;
"toolkit.telemetry.rejected" = true;
"toolkit.telemetry.server" = "";
"toolkit.telemetry.shutdownPingSender.enabled" = false;
"toolkit.telemetry.unified" = false;
"toolkit.telemetry.unifiedIsOptIn" = false;
"toolkit.telemetry.updatePing.enabled" = false;
"ui.prefersReducedMotion" = 1;
};
in {
default = {
id = 0;
isDefault = true;
settings = defaultSettings;
# extensions = with pkgs.nur.repos.rycee.firefox-addons; [
# ublock-origin
# darkreader
# sponsorblock
# consent-o-matic
# i-dont-care-about-cookies
# # auto-tab-discard TODO what is this
# ];
userChrome = ''
#TabsToolbar {
visibility: collapse !important;
}
'';
};
};
};
};
home-manager.users.me = {
stylix.targets.firefox.profileNames = [ "default" ];
};
environment.variables.BROWSER = "firefox";
}

View File

@@ -1,38 +1,28 @@
{ pkgs, ... }:
{
networking.networkmanager.ensureProfiles.profiles = {
"39C3" = {
connection = {
id = "39C3";
type = "wifi";
};
wifi = {
mode = "infrastructure";
ssid = "39C3";
};
wifi-security = {
auth-alg = "open";
key-mgmt = "wpa-eap";
};
"802-1x" = {
anonymous-identity = "39C3";
eap = "ttls;";
identity = "39C3";
password = "39C3";
phase2-auth = "pap";
altsubject-matches = "DNS:radius.c3noc.net";
ca-cert = "${builtins.fetchurl {
url = "https://letsencrypt.org/certs/isrgrootx1.pem";
sha256 = "sha256:1la36n2f31j9s03v847ig6ny9lr875q3g7smnq33dcsmf2i5gd92";
}}";
};
ipv4 = {
method = "auto";
};
ipv6 = {
addr-gen-mode = "default";
method = "auto";
};
};
{pkgs, ...}:
# https://paste.sr.ht/~erictapen/11716989e489b600f237041b6d657fdf0ee17b34
let
certificate = pkgs.stdenv.mkDerivation rec {
name = "dst-root-ca-x3.pem";
src = builtins.toFile "${name}.sed" ''
1,/DST Root CA X3/d
1,/-----END CERTIFICATE-----/p
'';
nativeBuildInputs = with pkgs; [cacert gnused];
phases = "installPhase";
installPhase = ''
${pkgs.gnused}/bin/sed -n -f $src ${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt > $out
'';
};
in {
networking.wireless.networks."36C3" = {
auth = ''
key_mgmt=WPA-EAP
eap=TTLS
identity="kmein"
password=" "
ca_cert="${certificate}"
altsubject_match="DNS:radius.c3noc.net"
phase2="auth=PAP"
'';
};
}

View File

@@ -2,7 +2,6 @@
config,
pkgs,
...
}:
{
}: {
services.clipmenu.enable = true;
}

View File

@@ -3,8 +3,9 @@
lib,
pkgs,
...
}:
{
}: let
inherit (import ../lib) tmpfilesConfig;
in {
systemd.user.services.systemd-tmpfiles-clean = {
enable = true;
wantedBy = [ "default.target" ];
@@ -15,40 +16,27 @@
};
};
systemd.user.tmpfiles.users.me.rules =
map pkgs.lib.niveum.tmpfilesConfig [
{
type = "d";
mode = "0755";
age = "7d";
path = "${config.users.users.me.home}/sync/Downloads";
}
{
type = "d";
mode = "0755";
age = "7d";
path = "${config.users.users.me.home}/cloud/nextcloud/tmp";
}
]
++
map
(
path:
pkgs.lib.niveum.tmpfilesConfig {
type = "L+";
user = config.users.users.me.name;
group = config.users.users.me.group;
mode = "0755";
argument = "${config.users.users.me.home}/sync/${path}";
path = "${config.users.users.me.home}/${path}";
}
)
[
".ssh"
".gnupg"
".pki"
".local/share/aerc"
];
systemd.user.tmpfiles.users.me.rules = map tmpfilesConfig [
{
type = "d";
mode = "0755";
age = "7d";
path = "${config.users.users.me.home}/sync/Downloads";
}
{
type = "d";
mode = "0755";
age = "7d";
path = "${config.users.users.me.home}/cloud/nextcloud/tmp";
}
] ++ map (path: tmpfilesConfig {
type = "L+";
user = config.users.users.me.name;
group = config.users.users.me.group;
mode = "0755";
argument = "${config.users.users.me.home}/sync/${path}";
path = "${config.users.users.me.home}/${path}";
}) [".ssh" ".gnupg" ".pki" ".local/share/aerc"];
services.gnome.gnome-keyring.enable = true;
security.pam.services.lightdm.enableGnomeKeyring = true;
@@ -62,22 +50,20 @@
systemd.user.services.nextcloud-syncer = {
enable = false;
wants = [ "network-online.target" ];
wantedBy = [ "default.target" ];
wants = ["network-online.target"];
wantedBy = ["default.target"];
startAt = "*:00/10";
script =
let
kieran = {
user = "kieran";
passwordFile = config.age.secrets.nextcloud-password-kieran.path;
endpoint = "https://cloud.kmein.de";
target = "${config.users.users.me.home}/notes";
};
in
''
mkdir -p ${lib.escapeShellArg kieran.target}
${pkgs.nextcloud-client}/bin/nextcloudcmd --non-interactive --user ${kieran.user} --password "$(cat ${kieran.passwordFile})" --path /Notes ${lib.escapeShellArg kieran.target} ${kieran.endpoint}
'';
script = let
kieran = {
user = "kieran";
passwordFile = config.age.secrets.nextcloud-password-kieran.path;
endpoint = "https://cloud.kmein.de";
target = "${config.users.users.me.home}/notes";
};
in ''
mkdir -p ${lib.escapeShellArg kieran.target}
${pkgs.nextcloud-client}/bin/nextcloudcmd --non-interactive --user ${kieran.user} --password "$(cat ${kieran.passwordFile})" --path /Notes ${lib.escapeShellArg kieran.target} ${kieran.endpoint}
'';
serviceConfig = {
Type = "oneshot";
Restart = "on-failure";
@@ -93,22 +79,19 @@
} | ${pkgs.fzf}/bin/fzf)"
exec ${pkgs.zathura}/bin/zathura "$book"
'')
(
let
kieran = {
user = "kieran.meinhardt@gmail.com";
passwordFile = config.age.secrets.mega-password.path;
};
megatools =
command:
''${pkgs.megatools}/bin/megatools ${command} --username ${lib.escapeShellArg kieran.user} --password "$(cat ${kieran.passwordFile})"'';
in
(let
kieran = {
user = "kieran.meinhardt@gmail.com";
passwordFile = config.age.secrets.mega-password.path;
};
megatools = command: ''${pkgs.megatools}/bin/megatools ${command} --username ${lib.escapeShellArg kieran.user} --password "$(cat ${kieran.passwordFile})"'';
in
pkgs.writers.writeDashBin "book-mega" ''
set -efu
selection="$(${megatools "ls"} | ${pkgs.fzf}/bin/fzf)"
test -n "$selection" || exit 1
tmpdir="$(mktemp -p "$XDG_RUNTIME_DIR" -d)"
tmpdir="$(mktemp -d)"
trap clean EXIT
clean() {
rm -rf "$tmpdir"
@@ -119,8 +102,7 @@
${megatools "get"} "$selection"
exec ${pkgs.zathura}/bin/zathura "$(basename "$selection")"
)
''
)
'')
];
age.secrets.mega-password = {
@@ -139,25 +121,16 @@
cert = config.age.secrets.syncthing-cert.path;
key = config.age.secrets.syncthing-key.path;
settings = {
devices = pkgs.lib.niveum.syncthingIds;
inherit ((import ../lib).syncthing) devices;
folders = {
"${config.users.users.me.home}/sync" = {
devices = [
"kabsa"
"manakish"
"fatteh"
];
devices = ["kabsa" "manakish" "fatteh"];
label = "sync";
versioning.type = "trashcan";
versioning.params.cleanoutDays = 100;
};
"${config.users.users.me.home}/mobile" = {
devices = [
"kabsa"
"manakish"
"fatteh"
"kibbeh"
];
devices = ["kabsa" "manakish" "fatteh" "kibbeh"];
id = "mobile";
label = "mobile";
versioning.type = "trashcan";

View File

@@ -2,13 +2,20 @@
pkgs,
lib,
config,
niveumPackages,
unstablePackages,
inputs,
...
}:
let
inherit (lib.strings) makeBinPath;
inherit (import ../lib) localAddresses kieran remoteDir;
defaultApplications = (import ../lib).defaultApplications { inherit pkgs; };
in
{
imports = [
inputs.self.nixosModules.system-dependent
inputs.self.nixosModules.power-action
{
boot.supportedFilesystems = [ "ntfs" ];
}
@@ -16,7 +23,13 @@ in
nixpkgs = {
config = {
allowUnfree = true;
packageOverrides = pkgs: {
dmenu = pkgs.writers.writeDashBin "dmenu" ''exec ${pkgs.wofi}/bin/wofi -dmenu "$@"'';
};
permittedInsecurePackages = [
"qtwebkit-5.212.0-alpha4"
"zotero-6.0.26"
"electron-25.9.0"
];
};
};
@@ -31,7 +44,7 @@ in
file = ../secrets/di-fm-key.age;
owner = config.users.users.me.name;
group = config.users.users.me.group;
mode = "440";
mode = "400";
};
restic = {
file = ../secrets/restic.age;
@@ -59,15 +72,13 @@ in
users.users.me = {
name = "kfm";
description = pkgs.lib.niveum.kieran.name;
description = kieran.name;
hashedPasswordFile = config.age.secrets.kfm-password.path;
isNormalUser = true;
uid = 1000;
extraGroups = [
"pipewire"
"audio"
"lp"
"scanner"
];
};
@@ -83,14 +94,19 @@ in
environment.interactiveShellInit = "export PATH=$PATH";
environment.shellAliases =
let
swallow = command: "${pkgs.swallow}/bin/swallow ${command}";
swallow = command: "${niveumPackages.swallow}/bin/swallow ${command}";
in
{
o = "${pkgs.xdg-utils}/bin/xdg-open";
ns = "nix-shell --run zsh";
pbcopy = "${pkgs.wl-clipboard}/bin/wl-copy";
pbpaste = "${pkgs.wl-clipboard}/bin/wl-paste";
tmux = "${pkgs.tmux}/bin/tmux -2";
sxiv = swallow "${pkgs.nsxiv}/bin/nsxiv";
zathura = swallow "${pkgs.zathura}/bin/zathura";
im = "${pkgs.openssh}/bin/ssh weechat@makanek -t screen -x weechat";
im = "${pkgs.openssh}/bin/ssh weechat@makanek -t tmux attach-session -t IM";
yt = "${pkgs.yt-dlp}/bin/yt-dlp --add-metadata -ic"; # Download video link
yta = "${pkgs.yt-dlp}/bin/yt-dlp --add-metadata --audio-format mp3 --audio-quality 0 -xic"; # Download with audio
yta = "${pkgs.yt-dlp}/bin/yt-dlp --add-metadata --audio-format opus --audio-quality 0 -xic"; # Download with audio
};
}
{
@@ -100,21 +116,39 @@ in
};
}
{
services.power-profiles-daemon.enable = true;
services.displayManager = {
autoLogin = {
enable = true;
user = config.users.users.me.name;
};
};
services.xserver = {
enable = true;
displayManager.lightdm = {
enable = true;
greeters.gtk = {
enable = true;
indicators = [
"~spacer"
"~host"
"~spacer"
"~session"
"~power"
];
};
};
};
}
{ programs.command-not-found.enable = true; }
{
programs.gnupg = {
agent = {
enable = true;
pinentryPackage = pkgs.pinentry-qt;
settings =
let
defaultCacheTtl = 2 * 60 * 60;
in
{
default-cache-ttl = defaultCacheTtl;
max-cache-ttl = 4 * defaultCacheTtl;
};
settings = rec {
default-cache-ttl = 2 * 60 * 60;
max-cache-ttl = 4 * default-cache-ttl;
};
};
};
@@ -132,7 +166,7 @@ in
}
{
services.getty = {
greetingLine = lib.mkForce "As-salamu alaykum wa rahmatullahi wa barakatuh!";
greetingLine = lib.mkForce "";
helpLine = lib.mkForce "";
};
}
@@ -140,85 +174,128 @@ in
networking.hosts = lib.mapAttrs' (name: address: {
name = address;
value = [ "${name}.local" ];
}) pkgs.lib.niveum.localAddresses;
}) localAddresses;
}
{
home-manager.users.me.home.stateVersion = "22.05";
home-manager.backupFileExtension = "bak";
}
{
systemd.user.services.udiskie = {
after = [ "udisks2.service" ];
wants = [ "udisks2.service" ];
wantedBy = [ "graphical-session.target" ];
serviceConfig = {
ExecStart = "${pkgs.udiskie}/bin/udiskie --verbose --no-config --notify";
};
};
services.udisks2.enable = true;
programs.dconf.enable = true;
home-manager.users.me = {
dconf.enable = true;
dconf.settings = {
# Change the default terminal for Nemo
"org/cinnamon/desktop/applications/terminal".exec = lib.getExe pkgs.niphas-terminal;
"org/cinnamon/desktop/applications/terminal".exec = defaultApplications.terminal;
};
};
}
./android.nix
./admin-essentials.nix
./stylix.nix
./alacritty.nix
./backup.nix
./bash.nix
./bluetooth.nix
./aerc.nix
./ccc.nix
./khal.nix
./browser.nix
./clipboard.nix
./cloud.nix
./direnv.nix
./docker.nix
./dunst.nix
./flix.nix
./fonts.nix
./fzf.nix
./git.nix
./hledger.nix
./htop.nix
./lix.nix
./uni.nix
# ./i3.nix
./graphical
./keyboard
./fu-berlin.nix
./i3.nix
./niri.nix
./i3status-rust.nix
./keyboard.nix
./mycelium.nix
./kdeconnect.nix
{ home-manager.users.me.home.file.".XCompose".source = ../lib/keyboards/XCompose; }
{ services.upower.enable = true; }
./lb.nix
./mpv.nix
./mime.nix
./editor.nix
./neovim.nix
./nix.nix
./newsboat.nix
./flameshot.nix
./fritzbox.nix
./packages.nix
./virtualization.nix
./picom.nix
./stardict.nix
./polkit.nix
./printing.nix
./redshift.nix
./retiolum.nix
./rofi.nix
./spacetime.nix
./ssh.nix
./sshd.nix
./sound.nix
./sudo.nix
./tmux.nix
./unclutter.nix
./vscode.nix
./watson.nix
./wallpaper.nix
./zsh.nix
{
home-manager.users.me.home.file.".zshrc".text = ''
# nothing to see here
'';
}
./tor.nix
./stw-berlin.nix
./mastodon-bot.nix
{
fileSystems."${remoteDir}/fritz" = {
device = "//192.168.178.1/FRITZ.NAS/Backup";
fsType = "cifs";
options = [
"username=ftpuser"
"password=ftppassword"
"noauto"
"nounix"
"rw"
# "noserverino" # ref https://askubuntu.com/a/1265165
"uid=${toString config.users.users.me.uid}"
"gid=${toString config.users.groups.users.gid}"
"x-systemd.automount"
"x-systemd.device-timeout=1"
"x-systemd.idle-timeout=1min"
];
};
}
{
programs.zsh.interactiveShellInit = ''
hash -d nixos=/etc/nixos niveum=${config.users.users.me.home}/sync/src/niveum
'';
home-manager.users.me = {
xdg.userDirs =
let
pictures = "${config.users.users.me.home}/cloud/nextcloud/Bilder";
in
{
enable = true;
documents = "${config.users.users.me.home}/cloud/nextcloud/Documents";
desktop = "/tmp";
download = "${config.users.users.me.home}/sync/Downloads";
music = "${config.users.users.me.home}/mobile/audio";
publicShare = "${config.users.users.me.home}/cloud/nextcloud/tmp";
videos = pictures;
pictures = pictures;
};
xdg.userDirs = rec {
enable = true;
documents = "${config.users.users.me.home}/cloud/nextcloud/Documents";
desktop = "/tmp";
download = "${config.users.users.me.home}/sync/Downloads";
music = "${config.users.users.me.home}/mobile/audio";
pictures = "${config.users.users.me.home}/cloud/nextcloud/Bilder";
publicShare = "${config.users.users.me.home}/cloud/nextcloud/tmp";
videos = pictures;
};
};
}
];

37
configs/direnv.nix Normal file
View File

@@ -0,0 +1,37 @@
{pkgs, ...}: let
nixify = pkgs.writers.writeDashBin "nixify" ''
set -efuC
if [ ! -e ./.envrc ]; then
echo use_nix > .envrc
direnv allow
fi
if [ ! -e shell.nix ]; then
cat > shell.nix <<'EOF'
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
packages = [];
}
EOF
''${EDITOR:-vim} shell.nix
fi
'';
in {
environment.systemPackages = [pkgs.direnv nixify];
home-manager.users.me.programs.direnv = {
enable = true;
stdlib = builtins.readFile "${
pkgs.fetchFromGitHub {
owner = "Mic92";
repo = "dotfiles";
rev = "a0a9b7e358fa70a85cd468f8ca1fbb02ae0a91df";
sha256 = "1y9h5s1lf59sczsm0ksq2x1yhl98ba9lwk5yil3q53rg7n4574pg";
}
}/home/.direnvrc";
};
programs.zsh.interactiveShellInit = ''
eval "$(${pkgs.direnv}/bin/direnv hook zsh)"
'';
}

15
configs/distrobump.nix Normal file
View File

@@ -0,0 +1,15 @@
{
lib,
config,
pkgs,
...
}: {
imports = [
(import <stockholm/makefu/3modules/bump-distrowatch.nix> {
inherit lib config;
pkgs = pkgs // {writeDash = pkgs.writers.writeDash;};
})
];
makefu.distrobump.enable = false;
}

16
configs/docker.nix Normal file
View File

@@ -0,0 +1,16 @@
{
lib,
pkgs,
...
}: {
virtualisation.docker = {
enable = true;
# for ICE wifi, ref https://gist.github.com/sunsided/7840e89ff4e11b64a2d7503fafa0290c
extraOptions = lib.concatStringsSep " " [
"--bip=172.39.1.5/24"
"--fixed-cidr=172.39.1.0/25"
];
};
users.users.me.extraGroups = ["docker"];
environment.systemPackages = [pkgs.docker pkgs.docker-compose];
}

65
configs/dunst.nix Normal file
View File

@@ -0,0 +1,65 @@
{
config,
pkgs,
...
}: let
inherit (import ../lib) defaultApplications theme;
sgr = code: string: ''\u001b[${code}m${string}\u001b[0m'';
in {
environment.systemPackages = [
(pkgs.writers.writeDashBin "notifications" ''
${pkgs.dunst}/bin/dunstctl history \
| ${pkgs.jq}/bin/jq -r '
.data[]
| map("${sgr "90" ''\(.appname.data)''} ${sgr "1" ''\(.summary.data)''} ${sgr "31" ''\(.body.data | gsub("\n"; " | "))''}")
| join("\n")'
'')
];
home-manager.users.me.services.dunst = {
enable = true;
iconTheme = (theme pkgs).icon;
settings = {
global = {
transparency = 10;
geometry = "200x5-30+20";
follow = "mouse";
indicate_hidden = true;
notification_height = 0;
separator_height = 2;
padding = 8;
horizontal_padding = 8;
sort = true;
markup = "full";
format = "%a\\n<b>%s</b>\\n%b";
alignment = "left";
show_age_threshold = 60;
bounce_freq = 0;
word_wrap = true;
ellipsize = "middle";
ignore_newline = false;
stack_duplicates = true;
hide_duplicate_count = false;
max_icon_size = 32;
sticky_history = true;
history_length = 20;
dmenu = "${pkgs.rofi}/bin/rofi -display-run dunst -show run";
browser = (defaultApplications pkgs).browser;
verbosity = "mesg";
corner_radius = 0;
mouse_left_click = "do_action";
mouse_right_click = "close_current";
mouse_middle_click = "close_all";
};
urgency_low = {
timeout = 5;
};
urgency_normal = {
timeout = 10;
};
urgency_critical = {
timeout = 0;
};
};
};
}

View File

@@ -2,10 +2,10 @@
lib,
pkgs,
...
}:
{
}: {
home-manager.users.me = {
services.flameshot = {
package = pkgs.flameshot.override { enableWlrSupport = true; };
enable = true;
settings.General = {
autoCloseIdleDaemon = true;
@@ -16,7 +16,7 @@
showHelp = false;
squareMagnifier = true;
uploadWithoutConfirmation = true;
# buttons = ''@Variant(\0\0\0\x7f\0\0\0\vQList<int>\0\0\0\0\x10\0\0\0\x2\0\0\0\x5\0\0\0\x13\0\0\0\xa\0\0\0\x1\0\0\0\xc\0\0\0\xd\0\0\0\x6\0\0\0\x8\0\0\0\0\0\0\0\xf\0\0\0\x4\0\0\0\xb\0\0\0\x3\0\0\0\x12\0\0\0\x9)'';
buttons = ''@Variant(\0\0\0\x7f\0\0\0\vQList<int>\0\0\0\0\x10\0\0\0\x2\0\0\0\x5\0\0\0\x13\0\0\0\xa\0\0\0\x1\0\0\0\xc\0\0\0\xd\0\0\0\x6\0\0\0\x8\0\0\0\0\0\0\0\xf\0\0\0\x4\0\0\0\xb\0\0\0\x3\0\0\0\x12\0\0\0\x9)'';
};
};
};

98
configs/flix.nix Normal file
View File

@@ -0,0 +1,98 @@
{
config,
pkgs,
...
}: let
flixLocation = "/media/flix";
flixLocationNew = "/media/flix-new";
cacheLocation = "/var/cache/flix";
indexFilename = "index";
indexFilenameNew = "index-new";
flixUser = "flix";
flixGroup = "users";
inherit (import ../lib) tmpfilesConfig;
in {
fileSystems.${flixLocation} = {
device = "prism.r:/export/download";
fsType = "nfs";
options = [
"noauto"
"noatime"
"nodiratime"
"x-systemd.automount"
"x-systemd.device-timeout=1"
"x-systemd.idle-timeout=1min"
"x-systemd.requires=tinc.retiolum.service"
"user"
"_netdev"
];
};
fileSystems.${flixLocationNew} = {
device = "//yellow.r/public";
fsType = "cifs";
options = [
"guest"
"nofail"
"noauto"
"ro"
"x-systemd.automount"
"x-systemd.device-timeout=1"
"x-systemd.idle-timeout=1min"
];
};
systemd.tmpfiles.rules = [
(tmpfilesConfig {
type = "d";
path = cacheLocation;
mode = "0750";
user = flixUser;
group = flixGroup;
})
];
systemd.services.flix-index = {
description = "Flix indexing service";
wants = ["network-online.target"];
script = ''
cp ${flixLocation}/index ./${indexFilename}
cp ${flixLocationNew}/index ./${indexFilenameNew}
'';
startAt = "hourly";
serviceConfig = {
Type = "oneshot";
User = flixUser;
Group = flixGroup;
WorkingDirectory = cacheLocation;
};
};
users.extraUsers.${flixUser} = {
isSystemUser = true;
createHome = true;
home = cacheLocation;
group = flixGroup;
};
environment.systemPackages = [
(pkgs.writers.writeDashBin "mpv-simpsons" ''
set -efu
cd "${flixLocation}/download"
[ -f "${cacheLocation}/${indexFilename}" ] || exit 1
cat "${cacheLocation}/${indexFilename}" \
| ${pkgs.gnugrep}/bin/grep -i 'simpsons.*mkv' \
| shuf \
| ${pkgs.findutils}/bin/xargs -d '\n' ${pkgs.mpv}/bin/mpv
'')
(pkgs.writers.writeDashBin "flixmenu" ''
set -efu
(
${pkgs.gnused}/bin/sed 's#^\.#${flixLocation}#' ${cacheLocation}/${indexFilename}
${pkgs.gnused}/bin/sed 's#^\.#${flixLocationNew}#' ${cacheLocation}/${indexFilenameNew}
) | ${pkgs.dmenu}/bin/dmenu -i -p flix -l 5 "$@" \
| ${pkgs.findutils}/bin/xargs -I '{}' ${pkgs.util-linux}/bin/setsid ${pkgs.xdg-utils}/bin/xdg-open '{}'
'')
];
}

View File

@@ -1,25 +1,22 @@
{
pkgs,
config,
niveumPackages,
...
}:
let
zip-font =
name: arguments:
let
directory = pkgs.fetchzip arguments;
in
pkgs.runCommand name { } ''
}: let
zip-font = name: arguments: let
directory = pkgs.fetchzip arguments;
in
pkgs.runCommand name {} ''
mkdir -p $out/share/fonts/{truetype,opentype,woff}
${pkgs.findutils}/bin/find ${directory} -name '*.ttf' -exec install '{}' $out/share/fonts/truetype \;
${pkgs.findutils}/bin/find ${directory} -name '*.otf' -exec install '{}' $out/share/fonts/opentype \;
${pkgs.findutils}/bin/find ${directory} -name '*.woff' -exec install '{}' $out/share/fonts/woff \;
'';
simple-ttf =
name: arguments:
let
file = pkgs.fetchurl arguments;
in
pkgs.runCommand name { } ''
simple-ttf = name: arguments: let
file = pkgs.fetchurl arguments;
in
pkgs.runCommand name {} ''
mkdir -p $out/share/fonts/truetype
install ${file} $out/share/fonts/truetype
'';
@@ -62,8 +59,7 @@ let
url = "https://github.com/microsoft/font-tools/raw/1092cb23520967830001a0807eb21d6a44dda522/EgyptianOpenType/font/eot.ttf";
sha256 = "1n294vhcx90270pnsw1dbk6izd61fjvbnjrh4hcf98ff3s540x0c";
};
in
{
in {
fonts = {
enableDefaultPackages = true;
fontDir.enable = true;
@@ -98,6 +94,7 @@ in
font-awesome
galatia-sil
gentium
# niveumPackages.gfs-fonts
gyre-fonts
ibm-plex
jetbrains-mono
@@ -106,45 +103,29 @@ in
lmodern
merriweather
ocr-a
montserrat
roboto
roboto-mono
noto-fonts
noto-fonts-cjk-sans
noto-fonts-color-emoji
noto-fonts-emoji
nerd-fonts.blex-mono
roboto-slab
scheherazade-new
source-code-pro
source-sans-pro
source-serif-pro
theano
tocharian-font
vista-fonts
niveumPackages.tocharian-font
vistafonts
vollkorn
zilla-slab
]; # google-fonts league-of-moveable-type
fontconfig.defaultFonts =
let
emoji = [ "Noto Color Emoji" ];
in
{
monospace = [ "Noto Sans Mono" ] ++ emoji;
serif = [
"Noto Serif"
"Noto Naskh Arabic"
"Noto Serif Devanagari"
];
sansSerif = [
"Noto Sans Display"
"Noto Naskh Arabic"
"Noto Sans Hebrew"
"Noto Sans Devanagari"
"Noto Sans CJK JP"
"Noto Sans Coptic"
"Noto Sans Syriac Western"
];
inherit emoji;
};
fontconfig.defaultFonts = rec {
monospace = [config.stylix.fonts.monospace.name] ++ emoji;
serif = [config.stylix.fonts.serif.name "Scheherazade New" "Ezra SIL" "Antinoou" "Noto Serif Devanagari"];
sansSerif = [config.stylix.fonts.sansSerif.name "Noto Sans Display" "Noto Naskh Arabic" "Noto Sans Hebrew" "Noto Sans Devanagari" "Noto Sans CJK JP" "Noto Sans Coptic" "Noto Sans Syriac Western"];
emoji = [config.stylix.fonts.emoji.name];
};
# xelatex fails with woff files
# ref https://tex.stackexchange.com/questions/392144/xelatex-and-fontspec-crash-trying-to-find-woff-file-for-some-fonts-but-not-other
fontconfig.localConf = ''

19
configs/fritzbox.nix Normal file
View File

@@ -0,0 +1,19 @@
{ config, ... }:
{
networking.firewall.allowedUDPPorts = [ 51820 ];
networking.wg-quick.interfaces.aether = {
autostart = false;
dns = ["192.168.178.1" "fritz.box"];
listenPort = 51820;
privateKeyFile = config.age.secrets.wireguard-aether-key.path;
peers = [
{
allowedIPs = ["192.168.178.0/24" "0.0.0.0/0"];
endpoint = "lng5gx2rmssv8ge1.myfritz.net:58997";
persistentKeepalive = 25;
presharedKeyFile = config.age.secrets.wireguard-aether-psk.path;
publicKey = "8Rr7BueC0CGmycBQFS7YM7VF7Adkdc1ZcLFy8YXyOQk=";
}
];
};
}

153
configs/fu-berlin.nix Normal file
View File

@@ -0,0 +1,153 @@
{
config,
pkgs,
lib,
...
}: let
username = "meinhak99";
inherit (import ../lib/email.nix) defaults pronouns;
inherit (import ../lib) remoteDir;
fu-defaults = rec {
imap.host = "mail.zedat.fu-berlin.de";
imap.port = 993;
imap.tls.enable = true;
smtp.host = imap.host;
smtp.port = 465;
smtp.tls.enable = true;
folders.drafts = "Entwürfe";
folders.sent = "Gesendet";
folders.trash = "Papierkorb";
};
in {
home-manager.users.me = {
programs.ssh = {
matchBlocks = {
fu-berlin = {
user = username;
hostname = "login.zedat.fu-berlin.de";
setEnv.TERM = "xterm";
};
};
};
accounts.email.accounts = {
fu-student =
lib.recursiveUpdate defaults
(lib.recursiveUpdate fu-defaults
rec {
userName = "meinhak99";
address = "kieran.meinhardt@fu-berlin.de";
aliases = ["${userName}@fu-berlin.de"];
passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.email-password-meinhak99.path}";
aerc.extraAccounts.signature-file = toString (pkgs.writeText "signature" signature.text);
signature = {
showSignature = "append";
text = ''
${defaults.realName}
${pronouns}
---
Studentische Hilfskraft / ZODIAC
Freie Universität Berlin
Telefon: +49 30 838 58118
Arnimallee 10, Raum 106, 14195 Berlin
'';
};
himalaya = {
enable = true;
settings.backend = "imap";
};
});
};
};
age.secrets = {
email-password-meinhak99 = {
file = ../secrets/email-password-meinhak99.age;
owner = config.users.users.me.name;
group = config.users.users.me.group;
mode = "400";
};
fu-sftp-key = {
file = ../secrets/fu-sftp-key.age;
owner = "root";
group = "root";
mode = "400";
};
};
# if it fails with "connection reset by peer" run `sudo sshfs ... ... -o ...` manually
# it needs to say 'yes' to the server's fingerprint
system.fsPackages = [ pkgs.sshfs ];
# https://www.zedat.fu-berlin.de/tip4u_157.pdf
fileSystems = let
fu-berlin-cifs-options = [
"uid=${toString config.users.users.me.uid}"
"gid=${toString config.users.groups.users.gid}"
"rw"
"nounix"
"domain=fu-berlin"
"noauto"
"x-systemd.automount"
"x-systemd.device-timeout=1"
"x-systemd.idle-timeout=1min"
];
firstCharacter = lib.strings.substring 0 1;
home-directory-mount = user: {
"${remoteDir}/fu/${user}/home" = {
device = "${user}@login.zedat.fu-berlin.de:/home/${firstCharacter user}/${user}";
fsType = "sshfs";
options = [
"allow_other"
"_netdev"
"x-systemd.automount"
"reconnect"
"ServerAliveInterval=15"
"IdentityFile=${config.age.secrets.fu-sftp-key.path}"
];
};
};
in {
"${remoteDir}/fu/zodiac" = {
device = "//trove.storage.fu-berlin.de/GESCHKULT";
fsType = "cifs";
options =
fu-berlin-cifs-options
++ [
"credentials=${config.age.secrets.cifs-credentials-zodiac.path}"
];
};
} // home-directory-mount "meinhak99"
// home-directory-mount "xm7234fu";
age.secrets = {
cifs-credentials-zodiac.file = ../secrets/cifs-credentials-zodiac.age;
};
environment.systemPackages = [
(pkgs.writers.writeDashBin "fu-vpn" ''
if ${pkgs.wirelesstools}/bin/iwgetid | ${pkgs.gnugrep}/bin/grep --invert-match eduroam
then
# root firefox will not open login window unless root owns Xauthority
sudo cp $XAUTHORITY /root/.Xauthority
sudo chown root: /root/.Xauthority
XAUTHORITY=/root/.Xauthority sudo ${pkgs.openconnect}/bin/openconnect vpn.fu-berlin.de --useragent=AnyConnect
fi
'')
];
systemd.services.fu-vpn = {
enable = false;
wants = ["network-online.target"];
serviceConfig.LoadCredential = "password:${config.age.secrets.email-password-meinhak99.path}";
script = ''
if ${pkgs.wirelesstools}/bin/iwgetid | ${pkgs.gnugrep}/bin/grep --invert-match eduroam
then
cat "$CREDENTIALS_DIRECTORY/password" | ${pkgs.openconnect}/bin/openconnect vpn.fu-berlin.de --user ${username} --passwd-on-stdin
fi
'';
};
}

55
configs/fysi.nix Normal file
View File

@@ -0,0 +1,55 @@
{
config,
lib,
pkgs,
...
}: let
inherit (import ../lib/email.nix) defaults;
sshIdentity = name: "${config.users.users.me.home}/.ssh/${name}";
in {
age.secrets = {
email-password-fysi = {
file = ../secrets/email-password-fysi.age;
owner = config.users.users.me.name;
group = config.users.users.me.group;
mode = "400";
};
};
home-manager.users.me = {
accounts.email.accounts = {
fysi =
lib.recursiveUpdate defaults
rec {
address = "kieran@fysi.tech";
userName = address;
passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.email-password-fysi.path}";
flavor = "fastmail.com";
};
};
programs.ssh.matchBlocks = rec {
"nextcloud.fysi.dev" = {
hostname = "116.203.82.203";
user = "root";
};
"lingua.miaengiadina.ch" = {
hostname = "135.181.85.233";
user = "root";
};
"cms-dev.woc2023.app".identityFile = sshIdentity "fysiweb";
"cms-master.woc2023.app".identityFile = sshIdentity "fysiweb";
"fysi-dev1" = {
hostname = "94.130.229.139";
user = "root";
identityFile = sshIdentity "fysiweb";
};
${fysi-dev1.hostname} = fysi-dev1;
"fysi-shared0" = {
hostname = "49.12.205.235";
user = "root";
identityFile = sshIdentity "fysiweb";
};
};
};
}

22
configs/fzf.nix Normal file
View File

@@ -0,0 +1,22 @@
{pkgs, ...}: {
programs.fzf = {
fuzzyCompletion = true;
keybindings = true;
};
home-manager.users.me = {
programs.fzf = rec {
enable = true;
defaultCommand = "${pkgs.fd}/bin/fd --type f --strip-cwd-prefix --follow --no-ignore-vcs --exclude .git";
defaultOptions = ["--height=40%"];
changeDirWidgetCommand = "${pkgs.fd}/bin/fd --type d";
changeDirWidgetOptions = [
"--preview='${pkgs.tree}/bin/tree -L 1 {}'"
"--bind=space:toggle-preview"
"--preview-window=hidden"
];
fileWidgetCommand = defaultCommand;
fileWidgetOptions = ["--preview='head -$LINES {}'"];
};
};
}

View File

@@ -1,23 +0,0 @@
{ pkgs, ... }:
{
environment.systemPackages = [
pkgs.zeroad
pkgs.mari0
pkgs.luanti # fka minetest
# pkgs.openarena
# pkgs.teeworlds
pkgs.nethack
# pkgs.freeciv
# pkgs.lincity-ng
# pkgs.superTuxKart
pkgs.morris
pkgs.gnome-chess
pkgs.gnuchess
];
networking.firewall = {
# for 0ad multiplayer
allowedTCPPorts = [ 20595 ];
allowedUDPPorts = [ 20595 ];
};
}

63
configs/git.nix Normal file
View File

@@ -0,0 +1,63 @@
{
pkgs,
inputs,
...
}: let
inherit (import ../lib) kieran ignorePaths;
in {
environment.systemPackages = [
pkgs.mr
pkgs.gitFull
pkgs.git-crypt
pkgs.gitflow
pkgs.gh
pkgs.git-extras
# pkgs.git-trim
pkgs.git-absorb
pkgs.gitstats
pkgs.patch
pkgs.patchutils
inputs.self.packages.${pkgs.system}.git-preview
];
environment.shellAliases = {
gf = "git-flow";
g = "git";
};
home-manager.users.me = {
programs.git = {
enable = true;
package = pkgs.gitFull;
userName = kieran.name;
userEmail = kieran.email;
aliases = {
br = "branch";
co = "checkout";
ci = "commit";
cm = "commit -m";
amend = "commit --amend";
st = "status -s";
unstage = "reset HEAD --";
diffs = "diff --staged";
last = "log -1 HEAD";
logs = "log --pretty=oneline";
graph = "log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all";
};
ignores = ignorePaths;
extraConfig = {
pull.ff = "only";
rebase.autoStash = true;
merge.autoStash = true;
push.autoSetupRemote = true;
# # ref https://github.com/dandavison/delta
# core.pager = "${pkgs.delta}/bin/delta";
# interactive.diffFilter = "${pkgs.delta}/bin/delta --color-only";
# delta.navigate = true;
# merge.conflictStyle = "diff3";
# diff.colorMoved = "default";
};
};
};
}

View File

@@ -1,44 +0,0 @@
{
pkgs,
lib,
config,
...
}:
{
programs.hyprland = {
enable = true;
withUWSM = true;
xwayland.enable = true;
package = pkgs.hyprland;
portalPackage = pkgs.xdg-desktop-portal-hyprland;
};
programs.ydotool.enable = true;
xdg.portal = {
enable = true;
extraPortals = [
pkgs.xdg-desktop-portal-hyprland
pkgs.xdg-desktop-portal-gtk
];
config.common.default = "*";
};
services.dbus = {
implementation = "broker";
# needed for GNOME services outside of GNOME (?)
packages = [ pkgs.gcr ];
};
environment.systemPackages = [
pkgs.xdg-desktop-portal
pkgs.xdg-desktop-portal-hyprland
];
services.getty.autologinOnce = true;
services.getty.autologinUser = config.users.users.me.name;
home-manager.users.me = import ./home-manager.nix {
inherit lib pkgs config;
};
}

View File

@@ -1,415 +0,0 @@
{
lib,
pkgs,
config,
...
}:
let
klem = pkgs.klem.override {
options.dmenu = "${pkgs.dmenu}/bin/dmenu -i -p klem";
options.scripts = {
"p.r paste" = pkgs.writers.writeDash "p.r" ''
${pkgs.curl}/bin/curl -fSs http://p.r --data-binary @- \
| ${pkgs.coreutils}/bin/tail --lines=1 \
| ${pkgs.gnused}/bin/sed 's/\\<r\\>/krebsco.de/'
'';
"envs.sh paste" = pkgs.writers.writeDash "envs-host" ''
${pkgs.curl}/bin/curl -F "file=@-" https://envs.sh
'';
# this segfaults
# "envs.sh mirror" = pkgs.writers.writeDash "envs-mirror" ''
# ${pkgs.curl}/bin/curl -F "url=$(${pkgs.coreutils}/bin/cat)" https://envs.sh
# '';
"envs.sh shorten" = pkgs.writers.writeDash "envs-shorten" ''
${pkgs.curl}/bin/curl -F "shorten=$(${pkgs.coreutils}/bin/cat)" https://envs.sh
'';
"go.r shorten" = pkgs.writers.writeDash "go.r" ''
${pkgs.curl}/bin/curl -fSs http://go.r -F "uri=$(${pkgs.coreutils}/bin/cat)"
'';
"4d2.org paste" = pkgs.writers.writeDash "4d2-paste" ''
${pkgs.curl}/bin/curl -F "file=@-" https://depot.4d2.org/
'';
"0x0.st shorten" = pkgs.writers.writeDash "0x0.st" ''
${pkgs.curl}/bin/curl -fSs https://0x0.st -F "shorten=$(${pkgs.coreutils}/bin/cat)"
'';
"rot13" = pkgs.writers.writeDash "rot13" ''
${pkgs.coreutils}/bin/tr '[A-Za-z]' '[N-ZA-Mn-za-m]'
'';
"ipa" = pkgs.writers.writeDash "ipa" ''
${pkgs.ipa}/bin/ipa
'';
"betacode" = pkgs.writers.writeDash "betacode" ''
${pkgs.betacode}/bin/betacode
'';
"curl" = pkgs.writers.writeDash "curl" ''
${pkgs.curl}/bin/curl -fSs "$(${pkgs.coreutils}/bin/cat)"
'';
ocr = pkgs.writers.writeDash "ocr" ''
${pkgs.tesseract4}/bin/tesseract -l eng+deu - stdout
'';
emojai = pkgs.writers.writeDash "emojai" ''
${pkgs.curl}/bin/curl https://www.emojai.app/api/generate -X POST -H 'Content-Type: application/json' --data-raw "$(${pkgs.jq}/bin/jq -sR '{emoji:.}')" | ${pkgs.jq}/bin/jq -r .result
'';
};
};
arabic.workspaces = [
"١"
"٢"
"٣"
"٤"
"٥"
"٦"
"٧"
"٨"
"٩"
"١٠"
];
arabic.music = "الموسيقى";
arabic.obsidian = "السبج";
hindi.workspaces = [
""
""
""
""
""
""
""
""
""
""
];
hindi.music = "";
hindi.obsidian = "ि";
hebrew.workspaces = [
"א"
"ב"
"ג"
"ד"
"ה"
"ו"
"ז"
"ח"
"ט"
"י"
];
hebrew.music = "מוסיקה";
hebrew.obsidian = "אובסידיאן";
latin.workspaces = [
""
""
""
""
""
""
""
""
""
""
];
latin.music = "MVSICA";
latin.obsidian = "NOSCENDA";
greek.workspaces = [
"Α"
"Β"
"Γ"
"Δ"
"Ε"
"Ϛ"
"Ζ"
"Η"
"Θ"
"Ι"
];
greek.music = "ΜΟΥΣΙΚΗ";
greek.obsidian = "ΥΠΟΜΝΗΜΑΤΑ";
language = greek;
in
{
services.mako = {
enable = true;
settings.default-timeout = 10 * 1000;
};
programs.ashell = {
enable = true;
settings = {
# position = "bottom";
modules = {
left = [
"Workspaces"
[
"WindowTitle"
]
];
center = [ "Clock" ];
right = [
"KeyboardLayout"
[
"Tray"
"SystemInfo"
"Settings"
]
];
};
workspaces = {
enable_workspace_filling = false;
disable_special_workspaces = true;
visibility_mode = "MonitorSpecific";
workspace_names = language.workspaces;
};
keyboard_layout.labels = {
"de" = "🇩🇪";
};
window_title = {
mode = "Title";
truncate_title_after_length = 75;
};
media_player = {
max_title_length = 40;
};
system_info.indicators = [
"Cpu"
"Memory"
{ Disk = "/"; }
];
clock.format = "%Y-%m-%d (%j %a %W) %H:%M";
settings.indicators = [
"IdleInhibitor"
"PowerProfile"
"Audio"
"Bluetooth"
"Network"
"Vpn"
"Battery"
];
appearance = {
font_name = config.stylix.fonts.sansSerif.name;
backdrop = 0.3;
scale_factor = 0.85;
# style = "Solid";
};
};
};
services.hypridle = {
enable = true;
settings = {
general = {
after_sleep_cmd = "hyprctl dispatch dpms on";
ignore_dbus_inhibit = false;
lock_cmd = "hyprlock";
};
listener = [
{
timeout = 900;
on-timeout = "hyprlock";
}
{
timeout = 1200;
on-timeout = "hyprctl dispatch dpms off";
on-resume = "hyprctl dispatch dpms on";
}
];
};
};
programs.hyprlock = {
enable = true;
settings = {
animations.enabled = false;
general = {
hide_cursor = true;
ignore_empty_input = true;
};
};
};
gtk = {
enable = true;
iconTheme = {
name = "Adwaita";
package = pkgs.adwaita-icon-theme;
};
};
wayland.windowManager.hyprland =
let
mod = "SUPER";
in
{
enable = true;
systemd.enable = false;
systemd.variables = [ "--all" ];
settings = {
env = [
"XCURSOR_SIZE,${toString config.stylix.cursor.size}" # TODO
"HYPRCURSOR_SIZE,${toString config.stylix.cursor.size}" # TODO
"HYPRCURSOR_THEME,${config.stylix.cursor.name}"
"QT_QPA_PLATFORM=wayland"
"GDK_BACKEND=wayland"
"NIXOS_OZONE_WL=1"
];
permission = [
"${pkgs.xdg-desktop-portal-hyprland}/libexec/.xdg-desktop-portal-hyprland-wrapped, screencopy, allow"
];
monitor = [
"eDP-1, 1920x1080, 0x0, 1" # fatteh's display
"desc:Samsung Electric Company C27F390 HTQH602129, 1920x1080, 0x-1080, 1" # home
"desc:Dell Inc. DELL P2419HC 8L0FL03, 1920x1080, 0x-1080, 1" # amo
", preferred, auto, 1"
];
exec-once = [
(lib.getExe pkgs.ashell)
"hyprctl dispatch exec \"[workspace special:${language.obsidian} silent] obsidian\""
"${lib.getExe' pkgs.wl-clipboard "wl-paste"} -t text --watch ${lib.getExe pkgs.clipman} store"
(lib.getExe pkgs.hyprsunset)
(lib.getExe pkgs.hyprpaper)
];
device = [
{
name = "elan-touchscreen";
enabled = false;
}
];
general = {
gaps_in = 2;
gaps_out = 2;
border_size = 2;
resize_on_border = true;
allow_tearing = false;
layout = "dwindle";
};
decoration = {
rounding = 0;
rounding_power = 0;
active_opacity = 1.0;
inactive_opacity = 1.0;
shadow = {
enabled = false;
range = 4;
render_power = 3;
};
blur = {
enabled = false;
size = 3;
passes = 1;
vibrancy = 0.17;
};
};
animations = {
enabled = true;
animation = [
"global, 1, 2, default"
];
};
dwindle = {
preserve_split = true;
};
master.new_status = "master";
gesture = [
"3, horizontal, workspace"
];
input = {
kb_layout = "de";
kb_variant = "T3";
kb_options = "compose:caps,grp:ctrls_toggle";
follow_mouse = 1;
sensitivity = 0;
touchpad.natural_scroll = false;
};
bindm = [
"${mod}, mouse:272, movewindow"
"${mod}, mouse:273, resizewindow"
];
bindel = [
",XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"
",XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
",XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
",XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
",XF86MonBrightnessUp, exec, brightnessctl -e4 -n2 set 5%+"
",XF86MonBrightnessDown, exec, brightnessctl -e4 -n2 set 5%-"
", Print, exec, ${lib.getExe pkgs.niphas-screenshot} -m region --clipboard-only"
];
bindl = [
", XF86AudioNext, exec, playerctl next"
", XF86AudioPause, exec, playerctl play-pause"
", XF86AudioPlay, exec, playerctl play-pause"
", XF86AudioPrev, exec, playerctl previous"
];
bind = [
"${mod}, Return, exec, ${lib.getExe pkgs.niphas-terminal}"
"${mod} SHIFT, Q, killactive,"
"${mod} SHIFT, R, exit,"
"${mod}, t, exec, ${lib.getExe pkgs.niphas-file-browser}"
"${mod}, Y, exec, ${lib.getExe pkgs.niphas-web-browser}"
"${mod}, Q, exec, ${lib.getExe pkgs.clipman} pick --tool=rofi"
"${mod}, u, exec, ${lib.getExe pkgs.unicodmenu}"
"${mod}, p, exec, ${lib.getExe pkgs.rofi-pass-wayland}"
"${mod} SHIFT, Z, togglefloating,"
"${mod}, D, exec, ${lib.getExe pkgs.rofi} -show run"
"${mod}, E, togglesplit," # dwindle
"${mod}, F, fullscreen"
"${mod}, G, moveoutofgroup"
"${mod} SHIFT, G, togglegroup"
"${mod}, h, movefocus, l"
"${mod}, l, movefocus, r"
"${mod}, k, movefocus, u"
"${mod}, j, movefocus, d"
"${mod}, F12, exec, ${klem}/bin/klem"
"${mod} SHIFT, W, exec, hyprlock"
"${mod} SHIFT, H, movewindow, l"
"${mod} SHIFT, L, movewindow, r"
"${mod} SHIFT, K, movewindow, u"
"${mod} SHIFT, J, movewindow, d"
"${mod}, S, togglespecialworkspace, ${language.music}"
"${mod} SHIFT, S, movetoworkspace, special:${language.music}"
"${mod}, O, togglespecialworkspace, ${language.obsidian}"
"${mod} SHIFT, O, movetoworkspace, special:${language.obsidian}"
]
++ lib.concatMap (
i:
let
key = lib.mod i 10;
in
[
"${mod}, ${toString key}, workspace, ${toString i}"
"${mod} SHIFT, ${toString key}, movetoworkspace, ${toString i}"
]
) (lib.range 1 10);
windowrule = [
"suppressevent maximize, class:.*" # ignore maximize requests from apps
"nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0" # fix some dragging issues with wayyland
"float,title:^(Picture-in-Picture)$"
"pin,title:^(Picture-in-Picture)$"
"size 640 360,title:^(Picture-in-Picture)$"
"move 100%-640 100%-360,title:^(Picture-in-Picture)$"
];
};
extraConfig = ''
bind = ${mod}, R, submap, resize
submap = resize
binde = , l, resizeactive, 50 0
binde = , h, resizeactive, -50 0
binde = , k, resizeactive, 0 -50
binde = , j, resizeactive, 0 50
bind = , escape, submap, reset
submap = reset
'';
};
}

View File

@@ -1,28 +1,26 @@
{
pkgs,
...
}:
let
}: let
ledgerDirectory = "/home/kfm/sync/src/ledger";
in
{
environment.systemPackages =
let
git = "${pkgs.git}/bin/git -C ${ledgerDirectory}";
in
[
pkgs.hledger
(pkgs.writers.writeDashBin "hledger-git" ''
if [ "$1" = entry ]; then
${pkgs.hledger}/bin/hledger balance -V > "${ledgerDirectory}/balance.txt"
${git} add balance.txt
${git} commit --all --message="$(date -Im)"
else
${git} $*
fi
'')
(pkgs.writers.writeDashBin "hledger-edit" ''
$EDITOR ${ledgerDirectory}/current.journal
'')
];
hora = pkgs.callPackage ../packages/hora.nix { timeLedger = "${ledgerDirectory}/time.timeclock"; };
in {
environment.systemPackages = let
git = "${pkgs.git}/bin/git -C ${ledgerDirectory}";
in [
hora
pkgs.hledger
(pkgs.writers.writeDashBin "hledger-git" ''
if [ "$1" = entry ]; then
${pkgs.hledger}/bin/hledger balance -V > "${ledgerDirectory}/balance.txt"
${git} add balance.txt
${git} commit --all --message="$(date -Im)"
else
${git} $*
fi
'')
(pkgs.writers.writeDashBin "hledger-edit" ''
$EDITOR ${ledgerDirectory}/current.journal
'')
];
}

View File

@@ -22,18 +22,8 @@
sort_key = "PERCENT_CPU";
tree_view = false;
update_process_names = false;
right_meters = [
"Uptime"
"Tasks"
"LoadAverage"
"Battery"
];
left_meters = [
"LeftCPUs2"
"RightCPUs2"
"Memory"
"Swap"
];
right_meters = ["Uptime" "Tasks" "LoadAverage" "Battery"];
left_meters = ["LeftCPUs2" "RightCPUs2" "Memory" "Swap"];
};
};
};

View File

@@ -2,12 +2,18 @@
config,
pkgs,
lib,
niveumPackages,
...
}:
let
klem = pkgs.klem.override {
options.dmenu = "${pkgs.dmenu}/bin/dmenu -i -p klem";
options.scripts = {
}: let
dashboard = pkgs.writers.writeDashBin "dashboard" ''
${pkgs.alacritty}/bin/alacritty --option font.size=4 --class dashboard --command ${pkgs.writers.writeDash "dashboard-inner" ''
exec ${pkgs.procps}/bin/watch -c -n 10 ${niveumPackages.q}/bin/q
''}
'';
inherit (import ../lib) defaultApplications;
klem = niveumPackages.klem.override {
config.dmenu = "${pkgs.dmenu}/bin/dmenu -i -p klem";
config.scripts = {
"p.r paste" = pkgs.writers.writeDash "p.r" ''
${pkgs.curl}/bin/curl -fSs http://p.r --data-binary @- \
| ${pkgs.coreutils}/bin/tail --lines=1 \
@@ -36,10 +42,10 @@ let
${pkgs.coreutils}/bin/tr '[A-Za-z]' '[N-ZA-Mn-za-m]'
'';
"ipa" = pkgs.writers.writeDash "ipa" ''
${pkgs.ipa}/bin/ipa
${niveumPackages.ipa}/bin/ipa
'';
"betacode" = pkgs.writers.writeDash "betacode" ''
${pkgs.betacode}/bin/betacode
${niveumPackages.betacode}/bin/betacode
'';
"curl" = pkgs.writers.writeDash "curl" ''
${pkgs.curl}/bin/curl -fSs "$(${pkgs.coreutils}/bin/cat)"
@@ -50,10 +56,15 @@ let
emojai = pkgs.writers.writeDash "emojai" ''
${pkgs.curl}/bin/curl https://www.emojai.app/api/generate -X POST -H 'Content-Type: application/json' --data-raw "$(${pkgs.jq}/bin/jq -sR '{emoji:.}')" | ${pkgs.jq}/bin/jq -r .result
'';
"gpt-3.5" = pkgs.writers.writeDash "gpt" ''
${niveumPackages.gpt35}/bin/gpt
'';
gpt-4 = pkgs.writers.writeDash "gpt" ''
${niveumPackages.gpt4}/bin/gpt
'';
};
};
in
{
in {
age.secrets = {
github-token-i3status-rust = {
file = ../secrets/github-token-i3status-rust.age;
@@ -75,20 +86,15 @@ in
};
};
environment.systemPackages = [
pkgs.xsecurelock
];
environment.sessionVariables = {
XSECURELOCK_NO_COMPOSITE = "1";
XSECURELOCK_BACKGROUND_COLOR = "navy";
XSECURELOCK_PASSWORD_PROMPT = "time_hex";
};
programs.slock.enable = true;
environment.systemPackages = [dashboard];
services.displayManager.defaultSession = "none+i3";
services.xserver = {
windowManager.i3 = {
enable = true;
package = pkgs.i3;
package = pkgs.i3-gaps;
};
};
@@ -107,224 +113,229 @@ in
'';
};
home-manager.users.me =
let
modifier = "Mod4";
infoWorkspace = "";
messageWorkspace = "";
modes.resize = {
"Escape" = ''mode "default"'';
"Return" = ''mode "default"'';
"h" = "resize shrink width 10 px or 5 ppt";
"j" = "resize grow height 10 px or 5 ppt";
"k" = "resize shrink height 10 px or 5 ppt";
"l" = "resize grow width 10 px or 5 ppt";
};
gaps.inner = 4;
floating = {
titlebar = false;
border = 1;
};
bars =
let
home-manager.users.me = let
modifier = "Mod4";
infoWorkspace = "";
messageWorkspace = "";
modes.resize = {
"Escape" = ''mode "default"'';
"Return" = ''mode "default"'';
"h" = "resize shrink width 10 px or 5 ppt";
"j" = "resize grow height 10 px or 5 ppt";
"k" = "resize shrink height 10 px or 5 ppt";
"l" = "resize grow width 10 px or 5 ppt";
};
gaps.inner = 4;
floating = {
titlebar = false;
border = 1;
};
bars = [
(config.home-manager.users.me.lib.stylix.i3.bar
// rec {
workspaceButtons = true;
mode = "hide"; # "dock";
position = "bottom";
in
[
(lib.recursiveUpdate config.home-manager.users.me.stylix.targets.i3.exportedBarConfig {
workspaceButtons = true;
mode = "hide"; # "dock";
inherit position;
statusCommand = toString (
pkgs.writers.writeDash "i3status-rust" ''
export I3RS_GITHUB_TOKEN="$(cat ${config.age.secrets.github-token-i3status-rust.path})"
export OPENWEATHERMAP_API_KEY="$(cat ${config.age.secrets.openweathermap-api-key.path})"
exec ${config.home-manager.users.me.programs.i3status-rust.package}/bin/i3status-rs ${config.home-manager.users.me.home.homeDirectory}/.config/i3status-rust/config-${position}.toml
''
);
fonts = {
names = [
"${config.stylix.fonts.sansSerif.name}"
"FontAwesome 6 Free"
];
size = config.stylix.fonts.sizes.desktop * 0.8;
};
})
];
window = {
titlebar = false;
border = 2;
hideEdgeBorders = "smart";
commands = [
{
criteria = {
class = "floating";
};
command = "floating enable";
}
{
criteria = {
class = "fzfmenu";
};
command = "floating enable";
}
{
criteria = {
class = ".*";
};
command = "border pixel 2";
}
{
criteria = {
class = "mpv";
};
command = lib.strings.concatStringsSep ", " [
"floating enable"
"sticky enable"
"fullscreen disable"
"resize set 640 480"
"move position mouse"
];
}
];
};
colors =
let
background = config.lib.stylix.colors.withHashtag.base00;
in
statusCommand = toString (pkgs.writers.writeDash "i3status-rust" ''
export I3RS_GITHUB_TOKEN="$(cat ${config.age.secrets.github-token-i3status-rust.path})"
export OPENWEATHERMAP_API_KEY="$(cat ${config.age.secrets.openweathermap-api-key.path})"
exec ${config.home-manager.users.me.programs.i3status-rust.package}/bin/i3status-rs ${config.home-manager.users.me.home.homeDirectory}/.config/i3status-rust/config-${position}.toml
'');
fonts = {
names = ["${config.stylix.fonts.sansSerif.name}" "FontAwesome 6 Free"];
size = config.stylix.fonts.sizes.desktop * 0.8;
};
})
];
window = {
titlebar = false;
border = 2;
hideEdgeBorders = "smart";
commands = [
{
unfocused = {
border = lib.mkForce background;
childBorder = lib.mkForce background;
criteria = {class = "floating";};
command = "floating enable";
}
{
criteria = {class = "fzfmenu";};
command = "floating enable";
}
{
criteria = {class = ".*";};
command = "border pixel 2";
}
{
criteria = {class = "mpv";};
command = lib.strings.concatStringsSep ", " [
"floating enable"
"sticky enable"
"fullscreen disable"
"resize set 640 480"
"move position mouse"
];
}
];
};
colors = let
background = config.lib.stylix.colors.withHashtag.base00;
in {
unfocused = {
border = lib.mkForce background;
childBorder = lib.mkForce background;
};
};
keybindings =
lib.listToAttrs (map (x: lib.nameValuePair "${modifier}+Shift+${toString x}" "move container to workspace ${toString x}") (lib.range 1 9))
// lib.listToAttrs (map (x: lib.nameValuePair "${modifier}+${toString x}" "workspace ${toString x}") (lib.range 1 9))
// {
"${modifier}+i" = "workspace ${infoWorkspace}";
"${modifier}+m" = "workspace ${messageWorkspace}";
"${modifier}+Shift+h" = "move left 25 px";
"${modifier}+Shift+j" = "move down 25 px";
"${modifier}+Shift+k" = "move up 25 px";
"${modifier}+Shift+l" = "move right 25 px";
"${modifier}+h" = "focus left";
"${modifier}+j" = "focus down";
"${modifier}+k" = "focus up";
"${modifier}+l" = "focus right";
# "${modifier}+Shift+b" = "move container to workspace prev";
# "${modifier}+Shift+n" = "move container to workspace next";
# "${modifier}+b" = "workspace prev";
# "${modifier}+n" = "workspace next";
"${modifier}+Shift+c" = "reload";
"${modifier}+Shift+q" = "kill";
"${modifier}+Shift+r" = "restart";
"${modifier}+z" = "sticky toggle";
"${modifier}+Shift+z" = "floating toggle";
"${modifier}+Shift+s" = "move scratchpad";
"${modifier}+s" = ''[class="^(?i)(?!obsidian).*"] scratchpad show'';
"${modifier}+o" = ''[class="obsidian"] scratchpad show'';
"${modifier}+c" = "split h";
"${modifier}+e" = "layout toggle split";
"${modifier}+f" = "fullscreen toggle";
"${modifier}+r" = "mode resize";
"${modifier}+v" = "split v";
"${modifier}+w" = "layout tabbed";
"${modifier}+q" = "exec ${config.services.clipmenu.package}/bin/clipmenu";
"${modifier}+Return" = "exec ${(defaultApplications pkgs).terminal}";
"${modifier}+t" = "exec ${(defaultApplications pkgs).fileManager}";
"${modifier}+y" = "exec ${(defaultApplications pkgs).browser}";
"${modifier}+d" = "exec ${pkgs.writers.writeDash "run" ''exec rofi -modi run,ssh,window -show run''}";
"${modifier}+Shift+d" = "exec ${niveumPackages.notemenu}/bin/notemenu";
"${modifier}+p" = "exec rofi-pass";
"${modifier}+Shift+p" = "exec rofi-pass --insert";
"${modifier}+u" = "exec ${niveumPackages.unicodmenu}/bin/unicodmenu";
"${modifier}+Shift+u" = "exec ${pkgs.writers.writeDash "last-unicode" ''${pkgs.xdotool}/bin/xdotool type --delay 1000 "$(${pkgs.gawk}/bin/awk 'END{print $1}' ~/.cache/unicodmenu)"''}";
"${modifier}+F7" = "exec ${pkgs.writers.writeDash "showkeys-toggle" ''
if ${pkgs.procps}/bin/pgrep screenkey; then
exec ${pkgs.procps}/bin/pkill screenkey
else
exec ${pkgs.screenkey}/bin/screenkey
fi
''}";
"${modifier}+F12" = "exec ${klem}/bin/klem";
"XF86AudioLowerVolume" = "exec ${pkgs.pamixer}/bin/pamixer -d 5";
"XF86AudioMute" = "exec ${pkgs.pamixer}/bin/pamixer -t";
"XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5";
"XF86Calculator" = "exec ${pkgs.st}/bin/st -c floating -e ${pkgs.bc}/bin/bc";
"XF86AudioPause" = "exec ${pkgs.playerctl}/bin/playerctl play-pause";
"XF86AudioPlay" = "exec ${pkgs.playerctl}/bin/playerctl play-pause";
"XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl next";
"XF86AudioPrev" = "exec ${pkgs.playerctl}/bin/playerctl previous";
"XF86AudioStop" = "exec ${pkgs.playerctl}/bin/playerctl stop";
"XF86ScreenSaver" = "exec ${niveumPackages.k-lock}/bin/k-lock";
# key names detected with xorg.xev:
# XF86WakeUp (fn twice)
# XF86Battery (fn f3)
# XF86Sleep (fn f4) - actually suspends
# XF86WLAN
# XF86WebCam (fn f6)
# XF86TouchpadToggle (fn f8)
# XF86Suspend (fn f12) - actually suspends to disk
# Num_Lock (fn Roll) - numlocks
# XF86Audio{Prev,Next,Mute,Play,Stop}
# XF86Forward
# XF86Back
# XF86Launch1 (thinkvantage)
};
in {
wayland.windowManager.sway = {
enable = true;
config = {
menu = "rofi -modi run,ssh,window -show run";
inherit modifier modes gaps bars floating window colors keybindings;
input = {
"*" = {
xkb_layout = "de";
xkb_variant = "T3";
};
};
keybindings =
lib.listToAttrs (
map (
x: lib.nameValuePair "${modifier}+Shift+${toString x}" "move container to workspace ${toString x}"
) (lib.range 1 9)
)
// lib.listToAttrs (
map (x: lib.nameValuePair "${modifier}+${toString x}" "workspace ${toString x}") (lib.range 1 9)
)
// {
"${modifier}+i" = "workspace ${infoWorkspace}";
"${modifier}+m" = "workspace ${messageWorkspace}";
"${modifier}+Shift+h" = "move left 25 px";
"${modifier}+Shift+j" = "move down 25 px";
"${modifier}+Shift+k" = "move up 25 px";
"${modifier}+Shift+l" = "move right 25 px";
"${modifier}+h" = "focus left";
"${modifier}+j" = "focus down";
"${modifier}+k" = "focus up";
"${modifier}+l" = "focus right";
# "${modifier}+Shift+b" = "move container to workspace prev";
# "${modifier}+Shift+n" = "move container to workspace next";
# "${modifier}+b" = "workspace prev";
# "${modifier}+n" = "workspace next";
"${modifier}+Shift+c" = "reload";
"${modifier}+Shift+q" = "kill";
"${modifier}+Shift+r" = "restart";
"${modifier}+z" = "sticky toggle";
"${modifier}+Shift+z" = "floating toggle";
"${modifier}+Shift+s" = "move scratchpad";
"${modifier}+s" = ''[class="^(?i)(?!obsidian).*"] scratchpad show'';
"${modifier}+o" = ''[class="obsidian"] scratchpad show'';
"${modifier}+c" = "split h";
"${modifier}+e" = "layout toggle split";
"${modifier}+f" = "fullscreen toggle";
"${modifier}+r" = "mode resize";
"${modifier}+v" = "split v";
"${modifier}+w" = "layout tabbed";
"${modifier}+q" = "exec ${config.services.clipmenu.package}/bin/clipmenu";
"${modifier}+Return" = "exec ${lib.getExe pkgs.niphas-terminal}";
"${modifier}+t" = "exec ${lib.getExe pkgs.niphas-file-browser}";
"${modifier}+y" = "exec ${lib.getExe pkgs.niphas-web-browser}";
"${modifier}+d" =
"exec ${pkgs.writers.writeDash "run" ''exec rofi -modi run,ssh,window -show run''}";
"${modifier}+Shift+d" = "exec ${lib.getExe pkgs.notemenu}";
"${modifier}+p" = "exec rofi-pass";
"${modifier}+Shift+p" = "exec rofi-pass --insert";
"${modifier}+u" = "exec ${lib.getExe pkgs.unicodmenu}";
"${modifier}+Shift+u" =
"exec ${pkgs.writers.writeDash "last-unicode" ''${pkgs.xdotool}/bin/xdotool type --delay 1000 "$(${pkgs.gawk}/bin/awk 'END{print $1}' ~/.cache/unicodmenu)"''}";
"${modifier}+F7" = "exec ${pkgs.writers.writeDash "showkeys-toggle" ''
if ${pkgs.procps}/bin/pgrep screenkey; then
exec ${pkgs.procps}/bin/pkill screenkey
else
exec ${pkgs.screenkey}/bin/screenkey
fi
''}";
"${modifier}+F12" = "exec ${klem}/bin/klem";
"XF86AudioLowerVolume" = "exec ${lib.getExe pkgs.pamixer} -d 5";
"XF86AudioMute" = "exec ${lib.getExe pkgs.pamixer} -t";
"XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5";
"XF86Calculator" = "exec ${lib.getExe pkgs.st} -c floating -e ${pkgs.bc}/bin/bc";
"XF86AudioPause" = "exec ${lib.getExe pkgs.playerctl} play-pause";
"XF86AudioPlay" = "exec ${lib.getExe pkgs.playerctl} play-pause";
"XF86AudioNext" = "exec ${lib.getExe pkgs.playerctl} next";
"XF86AudioPrev" = "exec ${lib.getExe pkgs.playerctl} previous";
"XF86AudioStop" = "exec ${lib.getExe pkgs.playerctl} stop";
# key names detected with xorg.xev:
# XF86WakeUp (fn twice)
# XF86Battery (fn f3)
# XF86Sleep (fn f4) - actually suspends
# XF86WLAN
# XF86WebCam (fn f6)
# XF86TouchpadToggle (fn f8)
# XF86Suspend (fn f12) - actually suspends to disk
# Num_Lock (fn Roll) - numlocks
# XF86Audio{Prev,Next,Mute,Play,Stop}
# XF86Forward
# XF86Back
# XF86Launch1 (thinkvantage)
terminal = (defaultApplications pkgs).terminal;
up = "k";
down = "j";
left = "h";
right = "l";
seat = {
"*" = {
hide_cursor = "when-typing enable";
};
};
in
{
stylix.targets.i3.enable = true;
startup = [
{command = "echo hello";}
];
};
};
xsession.windowManager.i3 = {
enable = true;
extraConfig = ''
bindsym --release ${modifier}+Shift+w exec xsecurelock
xsession.windowManager.i3 = {
enable = true;
extraConfig = ''
bindsym --release ${modifier}+Shift+w exec /run/wrappers/bin/slock
exec "${lib.getExe pkgs.obsidian}"
for_window [class="obsidian"] , move scratchpad
exec "${pkgs.obsidian}/bin/obsidian"
for_window [class="obsidian"] , move scratchpad
assign [class="message"] ${messageWorkspace}
exec "${pkgs.writers.writeDash "irc" "exec ${lib.getExe pkgs.alacritty} --class message -e ssh weechat@makanek -t tmux attach-session -t IM"}"
exec "${pkgs.writers.writeDash "email" "exec ${lib.getExe pkgs.alacritty} --class message -e aerc"}"
assign [class="message"] ${messageWorkspace}
exec "${pkgs.writers.writeDash "irc" "exec ${pkgs.alacritty}/bin/alacritty --class message -e ssh weechat@makanek -t tmux attach-session -t IM"}"
exec "${pkgs.writers.writeDash "email" "exec ${pkgs.alacritty}/bin/alacritty --class message -e aerc"}"
exec --no-startup-id ${pkgs.xss-lock}/bin/xss-lock -- xsecurelock
'';
config = {
inherit
modifier
gaps
modes
bars
floating
window
colors
;
keybindings = keybindings // {
assign [class="dashboard"] ${infoWorkspace}
exec ${dashboard}/bin/dashboard
'';
config = lib.mkMerge [
{
inherit modifier gaps modes bars floating window colors keybindings;
}
{
keybindings = let
new-workspace = pkgs.writers.writeDash "new-workspace" ''
i3-msg workspace $(($(i3-msg -t get_workspaces | tr , '\n' | grep '"num":' | cut -d : -f 2 | sort -rn | head -1) + 1))
'';
move-to-new-workspace = pkgs.writers.writeDash "new-workspace" ''
i3-msg move container to workspace $(($(i3-msg -t get_workspaces | tr , '\n' | grep '"num":' | cut -d : -f 2 | sort -rn | head -1) + 1))
'';
in {
"${modifier}+ß" = "exec ${niveumPackages.menu-calc}/bin/=";
"${modifier}+F6" = "exec ${pkgs.xorg.xkill}/bin/xkill";
"${modifier}+F9" = "exec ${pkgs.redshift}/bin/redshift -O 4000 -b 0.85";
"${modifier}+F10" = "exec ${pkgs.redshift}/bin/redshift -x";
"${modifier}+F11" = "exec ${pkgs.xcalib}/bin/xcalib -invert -alter";
"Print" = "exec flameshot gui";
# "${modifier}+Shift+x" = "exec ${move-to-new-workspace}";
# "${modifier}+x" = "exec ${new-workspace}";
"XF86Display" = "exec ${lib.getExe pkgs.dmenu-randr}";
"XF86Display" = "exec ${niveumPackages.dmenu-randr}/bin/dmenu-randr";
};
};
};
}
];
};
};
}

82
configs/i3status-rust.nix Normal file
View File

@@ -0,0 +1,82 @@
{
pkgs,
config,
...
}: {
age.secrets = {
miniflux-api-token = {
file = ../secrets/miniflux-api-token.age;
owner = config.users.users.me.name;
group = config.users.users.me.group;
mode = "400";
};
};
home-manager.users.me = {
programs.i3status-rust = {
enable = true;
bars.bottom = {
icons = "awesome6";
settings = {
theme.overrides = let
colours = config.lib.stylix.colors.withHashtag;
in {
idle_bg = colours.base00;
idle_fg = colours.base05;
good_bg = colours.base00;
good_fg = colours.base0B;
warning_bg = colours.base00;
warning_fg = colours.base0A;
critical_bg = colours.base00;
critical_fg = colours.base09;
info_bg = colours.base00;
info_fg = colours.base04;
separator_bg = colours.base00;
separator = " ";
};
};
blocks = [
{
block = "music";
format = "{$icon $combo $play |}";
separator = " ";
}
{
block = "net";
format = " $icon HU";
missing_format = "";
device = "ppp0";
}
{
block = "net";
format = " $icon FU";
missing_format = "";
device = "tun0";
}
{
block = "battery";
format = "$icon $percentage $time";
device = "DisplayDevice";
driver = "upower";
}
{
block = "sound";
}
{
block = "disk_space";
format = "$icon $available";
}
{
block = "memory";
format = "$icon $mem_used.eng(prefix:G)";
}
{block = "load";}
{
block = "time";
format = "$icon $timestamp.datetime(f:'%Y-%m-%d (%W %a) %H:%M', l:de_DE)";
}
];
};
};
};
}

98
configs/keyboard.nix Normal file
View File

@@ -0,0 +1,98 @@
{
pkgs,
lib,
...
}: let
commaSep = builtins.concatStringsSep ",";
xkbOptions = ["compose:caps" "terminate:ctrl_alt_bksp" "grp:ctrls_toggle"];
languages = {
arabic = { code = "ara"; variant = "buckwalter"; }; # ../lib/keyboards/arabic;
avestan = ../lib/keyboards/avestan;
coptic = ../lib/keyboards/coptic;
deutsch = { code = "de"; variant = "T3"; };
farsi = { code = "ir"; variant = "qwerty"; };
gothic = ../lib/keyboards/gothic;
greek = { code = "gr"; variant = "polytonic"; };
gujarati = {code = "in"; variant = "guj-kagapa"; };
hebrew = {code = "il"; variant = "phonetic";};
russian = { code = "ru"; variant = "phonetic"; };
sanskrit = { code = "in"; variant = "san-kagapa"; };
syriac = { code = "sy"; variant = "syc_phonetic"; };
urdu = {code = "in"; variant = "urd-phonetic"; };
};
defaultLanguage = languages.deutsch;
in {
services.libinput.enable = true;
# man 7 xkeyboard-config
services.xserver = {
# exportConfiguration = true; # link /usr/share/X11 properly
xkb.layout = defaultLanguage.code;
# T3: https://upload.wikimedia.org/wikipedia/commons/a/a9/German-Keyboard-Layout-T3-Version1-large.png
# buckwalter: http://www.qamus.org/transliteration.htm
xkb.variant = defaultLanguage.variant;
xkb.options = commaSep xkbOptions;
xkb.extraLayouts = {
"coptic" = {
languages = ["cop"];
description = "Coptic";
symbolsFile = ../lib/keyboards/coptic;
};
"gothic" = {
languages = ["got"];
description = "Gothic";
symbolsFile = ../lib/keyboards/gothic;
};
"avestan" = {
languages = ["ave"];
description = "Avestan";
symbolsFile = ../lib/keyboards/avestan;
};
"farsi-good" = {
languages = ["fas"];
description = "Farsi, but good";
symbolsFile = ../lib/keyboards/farsi;
};
};
};
environment.etc."x11-locale".source = toString pkgs.xorg.libX11 + "share/X11/locale";
console.keyMap = "de";
environment.systemPackages =
lib.mapAttrsToList
(language: settings:
let
code = if settings ? "code" then settings.code else language;
variant = if settings ? "variant" then settings.variant else "";
in
pkgs.writers.writeDashBin "kb-${language}" ''
${pkgs.xorg.setxkbmap}/bin/setxkbmap ${defaultLanguage.code},${code} ${defaultLanguage.variant},${variant} ${toString (map (option: "-option ${option}") xkbOptions)}
'')
languages ++
lib.mapAttrsToList
(language: settings:
let
code = if settings ? "code" then settings.code else language;
variant = if settings ? "variant" then settings.variant else "";
in
pkgs.writers.writeDashBin "kb-niri-${language}" ''
${pkgs.gnused}/bin/sed -i 's/^\(\s*layout\) ".*"$/\1 "${defaultLanguage.code},${code}"/;s/^\(\s*variant\) ".*"$/\1 "${defaultLanguage.variant},${variant}"/' ~/.config/niri/config.kdl
'') languages;
# improve held key rate
services.xserver.displayManager.sessionCommands = "${pkgs.xorg.xset}/bin/xset r rate 300 50";
systemd.user.services.gxkb = {
wantedBy = ["graphical-session.target"];
serviceConfig = {
SyslogIdentifier = "gxkb";
ExecStart = "${pkgs.gxkb}/bin/gxkb";
Restart = "always";
RestartSec = "15s";
StartLimitBurst = 0;
};
};
}

View File

@@ -1,143 +0,0 @@
{
config,
pkgs,
lib,
...
}:
let
commaSep = builtins.concatStringsSep ",";
xkbOptions = [
"compose:caps"
"terminate:ctrl_alt_bksp"
"grp:ctrls_toggle"
];
languages = {
deutsch = {
code = "de";
variant = "T3";
};
greek = {
code = "gr";
variant = "polytonic";
};
russian = {
code = "ru";
variant = "phonetic";
};
arabic = {
code = "ara";
variant = "buckwalter";
};
coptic = ./coptic;
avestan = ./avestan;
gothic = ./gothic;
farsi = {
code = "ir";
variant = "qwerty";
};
syriac = {
code = "sy";
variant = "syc_phonetic";
};
sanskrit = {
code = "in";
variant = "san-kagapa";
};
gujarati = {
code = "in";
variant = "guj-kagapa";
};
urdu = {
code = "in";
variant = "urd-phonetic";
};
hebrew = {
code = "il";
variant = "phonetic";
};
};
defaultLanguage = languages.deutsch;
in
{
services.libinput.enable = true;
# man 7 xkeyboard-config
services.xserver = {
exportConfiguration = lib.mkForce true; # link /usr/share/X11 properly
xkb.layout = defaultLanguage.code;
# T3: https://upload.wikimedia.org/wikipedia/commons/a/a9/German-Keyboard-Layout-T3-Version1-large.png
# buckwalter: http://www.qamus.org/transliteration.htm
xkb.variant = defaultLanguage.variant;
xkb.options = commaSep xkbOptions;
xkb.extraLayouts = {
coptic = {
languages = [ "cop" ];
description = "Coptic is the latest stage of the Egyptian language and was used by Egyptian Christians. The Coptic script is based on the Greek alphabet with some letters borrowed from Demotic Egyptian.";
symbolsFile = ./coptic;
};
avestan = {
languages = [ "ave" ];
description = "Avestan is an ancient Iranian language known primarily from its use in the sacred texts of Zoroastrianism, the Avesta. It is an Indo-Iranian language that was spoken in ancient Persia.";
symbolsFile = ./avestan;
};
gothic = {
languages = [ "got" ];
description = "Gothic is an extinct East Germanic language that was spoken by the Goths. It is known primarily from the Codex Argenteus, a 6th-century manuscript containing a translation of the Bible into Gothic.";
symbolsFile = ./gothic;
};
farsi = {
languages = [ "fas" ];
description = "Farsi, also known as Persian, is an Indo-Iranian language spoken primarily in Iran, Afghanistan (where it is known as Dari), and Tajikistan (where it is called Tajik). It has a rich literary tradition and is written in a modified Arabic script.";
symbolsFile = ./farsi;
};
};
};
environment.etc."x11-locale".source = toString pkgs.xorg.libX11 + "share/X11/locale";
home-manager.users.me = {
home.file = {
".XCompose".source = ./XCompose;
};
};
console.keyMap = "de";
environment.systemPackages = lib.mapAttrsToList (
language: settings:
let
code = if settings ? "code" then settings.code else language;
variant = if settings ? "variant" then settings.variant else "";
in
pkgs.writers.writeDashBin "kb-${language}" ''
if [ -n "$SWAYSOCK" ]; then
swaymsg -s $SWAYSOCK 'input * xkb_layout "${defaultLanguage.code},${code}"'
swaymsg -s $SWAYSOCK 'input * xkb_variant "${defaultLanguage.variant},${variant}"'
swaymsg -s $SWAYSOCK 'input * xkb_options "${lib.concatStringsSep "," xkbOptions}"'
elif [ -n "$HYPRLAND_INSTANCE_SIGNATURE" ]; then
hyprctl keyword input:kb_variant "" # otherwise we end up with an invalid combination for a short while
hyprctl keyword input:kb_layout "${defaultLanguage.code},${code}"
hyprctl keyword input:kb_variant "${defaultLanguage.variant},${variant}"
elif [ -n "$DISPLAY" ]; then
${pkgs.xorg.setxkbmap}/bin/setxkbmap ${defaultLanguage.code},${code} ${defaultLanguage.variant},${variant} ${
toString (map (option: "-option ${option}") xkbOptions)
}
fi
''
) (languages // config.services.xserver.xkb.extraLayouts);
# improve held key rate
services.xserver.displayManager.sessionCommands = "${pkgs.xorg.xset}/bin/xset r rate 300 50";
systemd.user.services.gxkb = {
wantedBy = [ "graphical-session.target" ];
serviceConfig = {
SyslogIdentifier = "gxkb";
ExecStart = "${pkgs.gxkb}/bin/gxkb";
Restart = "always";
RestartSec = "15s";
StartLimitBurst = 0;
};
};
}

View File

@@ -3,16 +3,19 @@
pkgs,
lib,
...
}:
let
}: let
davHome = "~/.local/share/dav";
kmeinCloud = {
davEndpoint = "https://cloud.kmein.de/remote.php/dav";
username = "kieran";
passwordFile = config.age.secrets.nextcloud-password-kieran.path;
};
in
{
fysiCloud = {
davEndpoint = "https://nextcloud.fysi.dev/remote.php/dav";
username = "kmein";
passwordFile = config.age.secrets.nextcloud-password-fysi.path;
};
in {
age.secrets = {
nextcloud-password-kieran = {
file = ../secrets/nextcloud-password-kieran.age;
@@ -20,6 +23,12 @@ in
group = config.users.users.me.group;
mode = "400";
};
nextcloud-password-fysi = {
file = ../secrets/nextcloud-password-fysi.age;
owner = config.users.users.me.name;
group = config.users.users.me.group;
mode = "400";
};
};
environment.systemPackages = [
@@ -41,8 +50,8 @@ in
systemd.user.services.vdirsyncer = {
enable = true;
wants = [ "network-online.target" ];
wantedBy = [ "default.target" ];
wants = ["network-online.target"];
wantedBy = ["default.target"];
startAt = "*:00/10";
script = ''
${pkgs.vdirsyncer}/bin/vdirsyncer sync && ${pkgs.khal}/bin/khal printcalendars # https://lostpackets.de/khal/configure.html#syncing

View File

@@ -2,11 +2,10 @@
lib,
pkgs,
...
}:
{
}: {
systemd.services.lb-subscription = {
enable = true;
wants = [ "network-online.target" ];
wants = ["network-online.target"];
startAt = "weekly";
serviceConfig = {
user = "kfm";

View File

@@ -1,11 +0,0 @@
{
pkgs,
lib,
...
}:
{
nix = {
package = lib.mkForce pkgs.lix;
settings.experimental-features = [ "nix-command" "flakes" ];
};
}

19
configs/mastodon-bot.nix Normal file
View File

@@ -0,0 +1,19 @@
{pkgs, ...}: {
systemd.services.imaginary-illuminations = {
enable = false;
wants = ["network-online.target"];
serviceConfig = {
User = "kfm";
Group = "users";
WorkingDirectory = "/home/kfm/cloud/Seafile/Documents/Media/imaginary-illuminations";
Restart = "on-failure";
RestartSec = "15s";
};
startAt = "7:00";
script = ''
${pkgs.deno}/bin/deno run -A post.ts
'';
};
systemd.timers.imaginary-illuminations.timerConfig.RandomizedDelaySec = "14h";
}

View File

@@ -2,8 +2,7 @@
config,
pkgs,
...
}:
{
}: {
services.nginx.virtualHosts.default = {
locations."= /stub_status".extraConfig = "stub_status;";
};
@@ -42,12 +41,12 @@
systemd.services.promtail = {
description = "Promtail service for Loki";
wantedBy = [ "multi-user.target" ];
wantedBy = ["multi-user.target"];
serviceConfig = {
ExecStart = ''
${pkgs.grafana-loki}/bin/promtail --config.file ${
(pkgs.formats.yaml { }).generate "promtail.yaml" {
(pkgs.formats.yaml {}).generate "promtail.yaml" {
server = {
http_listen_port = 28183;
grpc_listen_port = 0;
@@ -56,7 +55,9 @@
clients = [
{
url = "http://${
if config.networking.hostName == "makanek" then "127.0.0.1" else "makanek.r"
if config.networking.hostName == "makanek"
then "127.0.0.1"
else "makanek.r"
}:3100/loki/api/v1/push";
}
];
@@ -70,7 +71,7 @@
};
relabel_configs = [
{
source_labels = [ "__journal__systemd_unit" ];
source_labels = ["__journal__systemd_unit"];
target_label = "unit";
}
];

View File

@@ -1,42 +1,44 @@
{
pkgs,
lib,
self,
config,
niveumPackages,
...
}:
let
swallow = command: "${pkgs.swallow}/bin/swallow ${command}";
myMpv =
pkgs:
self.inputs.wrappers.wrapperModules.mpv.apply {
inherit pkgs;
scripts = [
pkgs.mpvScripts.visualizer
];
"mpv.conf".content = "";
"mpv.input".content = ''
Alt+- add video-zoom -0.25
Alt+= add video-zoom 0.25
Alt+LEFT add video-rotate -90
Alt+RIGHT add video-rotate 90
Alt+h add video-pan-x 0.05
Alt+j add video-pan-y -0.05
Alt+k add video-pan-y 0.05
Alt+l add video-pan-x -0.05
'';
};
in
{
}: let
swallow = command: "${niveumPackages.swallow}/bin/swallow ${command}";
in {
environment.shellAliases.smpv = swallow "mpv";
nixpkgs.overlays = [
(final: prev: {
mpv = (myMpv prev).wrapper;
(self: super: {
mpv = config.home-manager.users.me.programs.mpv.finalPackage;
})
];
environment.systemPackages = [
((myMpv pkgs).wrapper)
];
home-manager.users.me = {
programs.mpv = {
enable = true;
config = {
ytdl-format = "bestvideo[height<=?720][fps<=?30][vcodec!=?vp9]+bestaudio/best";
ytdl-raw-options = lib.concatStringsSep "," [''sub-lang="de,en"'' "write-sub=" "write-auto-sub="];
screenshot-template = "%F-%wH%wM%wS-%#04n";
script-opts = "ytdl_hook-ytdl_path=${pkgs.yt-dlp}/bin/yt-dlp";
ao = "pulse"; # no pipewire for me :(
};
bindings = {
"Alt+RIGHT" = "add video-rotate 90";
"Alt+LEFT" = "add video-rotate -90";
"Alt+-" = "add video-zoom -0.25";
"Alt+=" = "add video-zoom 0.25";
"Alt+l" = "add video-pan-x -0.05";
"Alt+h" = "add video-pan-x 0.05";
"Alt+k" = "add video-pan-y 0.05";
"Alt+j" = "add video-pan-y -0.05";
};
scripts = [
# pkgs.mpvScripts.quality-menu
niveumPackages.mpv-visualizer
];
};
};
}

View File

@@ -1,4 +1,7 @@
{ lib, pkgs, ... }:
{ lib, ... }:
let
myceliumAddresses = import ../lib/mycelium-network.nix;
in
{
services.mycelium = {
enable = true;
@@ -8,5 +11,5 @@
networking.hosts = lib.mapAttrs' (name: address: {
name = address;
value = [ "${name}.m" ];
}) pkgs.lib.niveum.myceliumAddresses;
}) myceliumAddresses;
}

View File

@@ -1,10 +1,14 @@
{
pkgs,
lib,
niveumPackages,
config,
...
}:
{
}: {
environment.variables.EDITOR = pkgs.lib.mkForce "nvim";
environment.shellAliases.vi = "nvim";
environment.shellAliases.vim = "nvim";
environment.shellAliases.view = "nvim -R";
home-manager.users.me = {
editorconfig = {
enable = true;
@@ -31,21 +35,24 @@
};
environment.systemPackages = [
pkgs.vim-typewriter
pkgs.dawn-editor
(pkgs.writers.writeDashBin "vim" ''neovim "$@"'')
(niveumPackages.vim.override {
stylixColors = config.lib.stylix.colors;
# colorscheme = "base16-gruvbox-light-medium";
})
# language servers
pkgs.pyright
pkgs.haskellPackages.haskell-language-server
pkgs.texlab
pkgs.gopls
pkgs.nil
pkgs.nixfmt-rfc-style
pkgs.rust-analyzer
pkgs.nodePackages.typescript-language-server
pkgs.lua-language-server
pkgs.nodePackages.vscode-langservers-extracted
pkgs.lemminx # XML LSP
pkgs.jq-lsp
pkgs.lemminx
niveumPackages.jq-lsp
pkgs.dhall-lsp-server
];
}

View File

@@ -0,0 +1,46 @@
{ pkgs, niveumPackages, config, ... }: {
environment.variables.EDITOR = pkgs.lib.mkForce "nvim";
environment.shellAliases.vi = "nvim";
environment.shellAliases.vim = "nvim";
environment.shellAliases.view = "nvim -R";
home-manager.users.me = {
editorconfig = {
enable = true;
settings = {
"*" = {
charset = "utf-8";
end_of_line = "lf";
trim_trailing_whitespace = true;
insert_final_newline = true;
indent_style = "space";
indent_size = 2;
};
"*.py" = { indent_size = 4; };
Makefile = { indent_style = "tab"; };
"*.md" = { trim_trailing_whitespace = false; };
};
};
};
environment.systemPackages = [
(pkgs.writers.writeDashBin "vim" ''neovim "$@"'')
(niveumPackages.vim.override {
stylixColors = config.lib.stylix.colors;
# colorscheme = "base16-gruvbox-dark-medium";
})
# language servers
pkgs.pyright
pkgs.haskellPackages.haskell-language-server
pkgs.texlab
pkgs.nil
pkgs.rust-analyzer
pkgs.nodePackages.typescript-language-server
pkgs.lua-language-server
pkgs.nodePackages.vscode-langservers-extracted
pkgs.lemminx
niveumPackages.jq-lsp
pkgs.dhall-lsp-server
];
}

View File

@@ -1,8 +1,7 @@
{
pkgs,
...
}:
{
}: {
programs.nm-applet.enable = true;
networking.networkmanager = {
@@ -13,10 +12,10 @@
];
wifi.macAddress = "random";
ethernet.macAddress = "random";
unmanaged = [ "docker*" ];
unmanaged = ["docker*"];
};
users.users.me.extraGroups = [ "networkmanager" ];
users.users.me.extraGroups = ["networkmanager"];
environment.systemPackages = [
pkgs.speedtest-cli

17
configs/newsboat.nix Normal file
View File

@@ -0,0 +1,17 @@
{
pkgs,
config,
...
}: {
environment.systemPackages = [
(pkgs.writers.writeDashBin "miniflux-watch-later" ''
miniflux_api_token=$(cat ${config.age.secrets.miniflux-api-token.path})
random_feed_item=$(
${pkgs.curl}/bin/curl -u "$miniflux_api_token" --basic -s 'https://feed.kmein.de/v1/entries?starred=true&limit=0' \
| ${pkgs.jq}/bin/jq -r '.entries[].id' \
| ${pkgs.coreutils}/bin/shuf -n1
)
${pkgs.xdg-utils}/bin/xdg-open "https://feed.kmein.de/starred/entry/$random_feed_item"
'')
];
}

445
configs/niri.nix Normal file
View File

@@ -0,0 +1,445 @@
{
pkgs,
config,
niveumPackages,
lib,
...
}:
let
inherit (import ../lib) defaultApplications;
niriConfig =
let
klem = niveumPackages.klem.override {
config.dmenu = "${pkgs.dmenu}/bin/dmenu -i -p klem";
config.scripts = {
"p.r paste" = pkgs.writers.writeDash "p.r" ''
${pkgs.curl}/bin/curl -fSs http://p.r --data-binary @- \
| ${pkgs.coreutils}/bin/tail --lines=1 \
| ${pkgs.gnused}/bin/sed 's/\\<r\\>/krebsco.de/'
'';
"envs.sh paste" = pkgs.writers.writeDash "envs-host" ''
${pkgs.curl}/bin/curl -F "file=@-" https://envs.sh
'';
"envs.sh shorten" = pkgs.writers.writeDash "envs-shorten" ''
${pkgs.curl}/bin/curl -F "shorten=$(${pkgs.coreutils}/bin/cat)" https://envs.sh
'';
"go.r shorten" = pkgs.writers.writeDash "go.r" ''
${pkgs.curl}/bin/curl -fSs http://go.r -F "uri=$(${pkgs.coreutils}/bin/cat)"
'';
"4d2.org paste" = pkgs.writers.writeDash "4d2-paste" ''
${pkgs.curl}/bin/curl -F "file=@-" https://depot.4d2.org/
'';
"0x0.st shorten" = pkgs.writers.writeDash "0x0.st" ''
${pkgs.curl}/bin/curl -fSs https://0x0.st -F "shorten=$(${pkgs.coreutils}/bin/cat)"
'';
"rot13" = pkgs.writers.writeDash "rot13" ''
${pkgs.coreutils}/bin/tr '[A-Za-z]' '[N-ZA-Mn-za-m]'
'';
"ipa" = pkgs.writers.writeDash "ipa" ''
${niveumPackages.ipa}/bin/ipa
'';
"betacode" = pkgs.writers.writeDash "betacode" ''
${niveumPackages.betacode}/bin/betacode
'';
"curl" = pkgs.writers.writeDash "curl" ''
${pkgs.curl}/bin/curl -fSs "$(${pkgs.coreutils}/bin/cat)"
'';
ocr = pkgs.writers.writeDash "ocr" ''
${pkgs.tesseract4}/bin/tesseract -l eng+deu - stdout
'';
emojai = pkgs.writers.writeDash "emojai" ''
${pkgs.curl}/bin/curl https://www.emojai.app/api/generate -X POST -H 'Content-Type: application/json' --data-raw "$(${pkgs.jq}/bin/jq -sR '{emoji:.}')" | ${pkgs.jq}/bin/jq -r .result
'';
"gpt-3.5" = pkgs.writers.writeDash "gpt" ''
${niveumPackages.gpt35}/bin/gpt
'';
gpt-4 = pkgs.writers.writeDash "gpt" ''
${niveumPackages.gpt4}/bin/gpt
'';
};
};
in
''
spawn-at-startup "${pkgs.ironbar}/bin/ironbar"
spawn-at-startup "${pkgs.xwayland-satellite}/bin/xwayland-satellite"
environment {
DISPLAY ":0"
ANKI_WAYLAND "1"
}
input {
warp-mouse-to-focus
focus-follows-mouse max-scroll-amount="0%"
keyboard {
repeat-rate 35
repeat-delay 350
track-layout "global"
xkb {
layout "de"
variant "T3"
options "ctrl:nocaps,compose:caps,grp:ctrls_toggle"
}
}
touchpad {
click-method "clickfinger"
tap
dwt
dwtp
}
}
prefer-no-csd
hotkey-overlay {
skip-at-startup
}
layout {
gaps 5
default-column-width {
proportion 0.5
}
preset-column-widths {
proportion 0.33333
proportion 0.5
proportion 0.66667
}
focus-ring {
width 2
}
shadow {
// on
softness 30
spread 5
offset x=0 y=5
draw-behind-window true
color "#00000070"
// inactive-color "#00000054"
}
tab-indicator {
// off
hide-when-single-tab
place-within-column
gap 5
width 4
length total-proportion=1.0
position "right"
gaps-between-tabs 2
corner-radius 8
active-color "red"
inactive-color "gray"
urgent-color "blue"
// active-gradient from="#80c8ff" to="#bbddff" angle=45
// inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
// urgent-gradient from="#800" to="#a33" angle=45
}
border {
off
}
}
animations {
// off
workspace-switch {
spring damping-ratio=1.0 stiffness=1000 epsilon=0.0001
}
window-open {
duration-ms 150
curve "ease-out-expo"
}
window-close {
duration-ms 150
curve "ease-out-quad"
}
horizontal-view-movement {
spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
}
window-movement {
spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
}
window-resize {
spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
}
config-notification-open-close {
spring damping-ratio=0.6 stiffness=1000 epsilon=0.001
}
screenshot-ui-open {
duration-ms 200
curve "ease-out-quad"
}
overview-open-close {
spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
}
}
window-rule {
geometry-corner-radius 0
clip-to-geometry true
}
window-rule {
match app-id="mpv"
open-floating true
}
window-rule {
match app-id="rofi"
open-floating true
}
window-rule {
match app-id=r#"firefox$"# title="^Picture-in-Picture$"
open-floating true
default-floating-position x=32 y=32 relative-to="bottom-left"
}
window-rule {
match is-window-cast-target=true
border {
on
width 3
active-color "#f38ba8"
inactive-color "#7d0d2d"
}
}
binds {
Mod+Shift+Slash { show-hotkey-overlay; }
Mod+Return { spawn "${(defaultApplications pkgs).terminal}"; }
Mod+D { spawn "${pkgs.wofi}/bin/wofi" "--show" "run"; }
Mod+Shift+D { spawn "${niveumPackages.notemenu}/bin/notemenu"; }
Mod+T { spawn "${(defaultApplications pkgs).fileManager}"; }
Mod+Y { spawn "${(defaultApplications pkgs).browser}"; }
Mod+P { spawn "${niveumPackages.passmenu}/bin/passmenu"; }
Mod+U { spawn "${niveumPackages.unicodmenu}/bin/unicodmenu"; }
Mod+Shift+Z { toggle-window-floating; }
Mod+B { spawn "${pkgs.ironbar}/bin/ironbar" "bar" "bar-1337" "toggle-visible"; }
Mod+F12 { spawn "${klem}/bin/klem"; }
Mod+Shift+Q { close-window; }
XF86AudioRaiseVolume allow-when-locked=true { spawn "${pkgs.pamixer}/bin/pamixer -i 5"; }
XF86AudioLowerVolume allow-when-locked=true { spawn "${pkgs.pamixer}/bin/pamixer -d 5"; }
XF86AudioMute allow-when-locked=true { spawn "${pkgs.pamixer}/bin/pamixer -t"; }
XF86AudioPause allow-when-locked=true { spawn "${pkgs.playerctl}/bin/playerctl play-pause"; }
XF86AudioPlay allow-when-locked=true { spawn "${pkgs.playerctl}/bin/playerctl play-pause"; }
XF86AudioNext allow-when-locked=true { spawn "${pkgs.playerctl}/bin/playerctl next"; }
XF86AudioPrev allow-when-locked=true { spawn "${pkgs.playerctl}/bin/playerctl previous"; }
XF86AudioStop allow-when-locked=true { spawn "${pkgs.playerctl}/bin/playerctl stop"; }
Print { spawn "flameshot gui"; }
Mod+Shift+W { spawn "swaylock"; }
Mod+Comma { consume-or-expel-window-left; }
Mod+Period { consume-or-expel-window-right; }
Mod+W { toggle-column-tabbed-display; }
Mod+A repeat=false { toggle-overview; }
Mod+F { maximize-column; }
Mod+C { center-column; }
Mod+Minus { set-column-width "-25%"; }
Mod+Plus { set-column-width "+25%"; }
Mod+Ctrl+0 { spawn "niri" "msg" "action" "switch-layout" "0"; }
Mod+Ctrl+1 { spawn "niri" "msg" "action" "switch-layout" "1"; }
Mod+Ctrl+2 { spawn "niri" "msg" "action" "switch-layout" "2"; }
Mod+Ctrl+3 { spawn "niri" "msg" "action" "switch-layout" "3"; }
Mod+Ctrl+4 { spawn "niri" "msg" "action" "switch-layout" "4"; }
Mod+Ctrl+5 { spawn "niri" "msg" "action" "switch-layout" "5"; }
Mod+Ctrl+6 { spawn "niri" "msg" "action" "switch-layout" "6"; }
Mod+Ctrl+7 { spawn "niri" "msg" "action" "switch-layout" "7"; }
Mod+Ctrl+8 { spawn "niri" "msg" "action" "switch-layout" "8"; }
Mod+Ctrl+9 { spawn "niri" "msg" "action" "switch-layout" "9"; }
Mod+H { focus-column-or-monitor-left; }
Mod+J { focus-window-or-workspace-down; }
Mod+K { focus-window-or-workspace-up; }
Mod+L { focus-column-or-monitor-right; }
Mod+Shift+H { move-column-left-or-to-monitor-left; }
Mod+Shift+J { move-window-down-or-to-workspace-down; }
Mod+Shift+K { move-window-up-or-to-workspace-up; }
Mod+Shift+L { move-column-right-or-to-monitor-right; }
Mod+Ctrl+H { focus-monitor-left; }
Mod+Ctrl+J { focus-monitor-down; }
Mod+Ctrl+K { focus-monitor-up; }
Mod+Ctrl+L { focus-monitor-right; }
Mod+Shift+Ctrl+H { move-column-to-monitor-left; }
Mod+Shift+Ctrl+J { move-column-to-workspace-down; }
Mod+Shift+Ctrl+K { move-column-to-workspace-up; }
Mod+Shift+Ctrl+L { move-column-to-monitor-right; }
Mod+Shift+Alt+Ctrl+H { move-workspace-to-monitor-left; }
Mod+Shift+Alt+Ctrl+J { move-workspace-down; }
Mod+Shift+Alt+Ctrl+K { move-workspace-up; }
Mod+Shift+Alt+Ctrl+L { move-workspace-to-monitor-right; }
Mod+1 { focus-workspace 1; }
Mod+2 { focus-workspace 2; }
Mod+3 { focus-workspace 3; }
Mod+4 { focus-workspace 4; }
Mod+5 { focus-workspace 5; }
Mod+6 { focus-workspace 6; }
Mod+7 { focus-workspace 7; }
Mod+8 { focus-workspace 8; }
Mod+9 { focus-workspace 9; }
Mod+0 { focus-workspace 10; }
Mod+Shift+1 { move-window-to-workspace "1"; }
Mod+Shift+2 { move-window-to-workspace "2"; }
Mod+Shift+3 { move-window-to-workspace "3"; }
Mod+Shift+4 { move-window-to-workspace "4"; }
Mod+Shift+5 { move-window-to-workspace "5"; }
Mod+Shift+6 { move-window-to-workspace "6"; }
Mod+Shift+7 { move-window-to-workspace "7"; }
Mod+Shift+8 { move-window-to-workspace "8"; }
Mod+Shift+9 { move-window-to-workspace "9"; }
Mod+Shift+0 { move-window-to-workspace "0"; }
}
'';
in
{
system.activationScripts.niriConfig = {
text = ''
cp ${pkgs.writeText "config.kdl" niriConfig} ${config.users.users.me.home}/.config/niri/config.kdl
chown ${config.users.users.me.name}:${config.users.users.me.group} ${config.users.users.me.home}/.config/niri/config.kdl
'';
};
programs.niri.enable = true;
services.displayManager.defaultSession = lib.mkForce "niri";
home-manager.users.me = {
xdg.configFile."ironbar/style.css".text = ''
* {
font-size: 8pt;
font-family: "Gentium Plus", "BlexMono Nerd Font";
}
box, menubar, button {
background-color: unset;
box-shadow: none;
background-image: none;
}
.clock, .upower, .volume {
font-weight: unset;
}
tooltip * {
font-family: "BlexMono Nerd Font";
font-size: 7pt;
}
'';
xdg.configFile."ironbar/config.json".source = (pkgs.formats.json { }).generate "ironbar.json" {
name = "bar-1337";
height = 12;
layer = "top";
position = "bottom";
start = [ ];
center = [
{
type = "tray";
icon_size = 8;
}
{ type = "clipboard"; }
{ type = "notifications"; }
];
end = [
{
type = "upower";
icon_size = 8;
format = "{percentage}%";
}
{
type = "label";
tooltip = "{{df -h --output=size,used,avail,pcent,target}}";
label = "\t{{5000:df -h / --output=avail | tail +2}}";
}
{
type = "label";
tooltip = "{{free -Lh --si | awk '{for(i=1;i<=NF;i++){printf \"%s%s\", $i, (i%2? OFS: ORS)} if(NF%2) printf ORS}'}}";
label = "󰍛\t{{500:free -h --si | awk 'NR==2{printf $3 \"\\n\"}'}}";
}
{
type = "label";
tooltip = "{{}}";
on_click_left = "pamixer -t";
on_scroll_up = "pamixer -i 1";
on_scroll_down = "pamixer -d 1";
label = "{{500:if $(pamixer --get-mute) = true; then echo ; else echo ; fi}}\t{{500:pamixer --get-volume}}%";
}
{
type = "label";
tooltip = "{{uptime}}";
label = "\t{{500:uptime | sed 's/.*load average: \\([^ ]*\\);.*/\\1/' | tr ' ' '\n'}}";
}
{
type = "label";
tooltip = "{{khal list today today -d astro-test-3 }}";
label = "";
}
{
type = "label";
tooltip = "{{curl wttr.in/?0 | ${pkgs.ansifilter}/bin/ansifilter}}";
label = "󰔏";
}
{
type = "label";
name = "cal";
tooltip = "{{cal}}";
label = "{{500:date +'<U+F017>\t%Y-%m-%d (%W %a) %H:%M'}}";
}
];
};
programs.alacritty.enable = true; # Super+T in the default setting (terminal)
programs.swaylock.enable = true; # Super+Alt+L in the default setting (screen locker)
services.swaync = {
enable = true;
settings = {
notification-window-width = 300;
control-center-width = 300;
widgets = [
"volume"
"mpris"
"title"
"dnd"
"notifications"
];
widget-config = {
title = {
text = "ϥ̄";
"clear-all-button" = true;
"button-text" = "";
};
dnd.text = "̄̄ϣ̄̄";
label.text = "";
};
};
};
services.swayidle.enable = true; # idle management daemon
home.packages = with pkgs; [
xdg-desktop-portal-gnome
swaybg
];
};
services.gnome.gnome-keyring.enable = true; # secret service
security.pam.services.swaylock = { };
}

14
configs/nix.nix Normal file
View File

@@ -0,0 +1,14 @@
{
pkgs,
inputs,
...
}: {
nixpkgs = {
config.allowUnfree = true;
};
nix = {
package = pkgs.nixVersions.stable;
extraOptions = "experimental-features = nix-command flakes";
nixPath = ["nixpkgs=${inputs.nixpkgs}"];
};
}

Some files were not shown because too many files have changed in this diff Show More